Perché PHP ha interfacce?


35

Ho notato che a partire da PHP5, le interfacce sono state aggiunte alla lingua. Tuttavia, poiché PHP è così tipicamente impresso, sembra che la maggior parte dei vantaggi dell'uso delle interfacce vada persa. Perché questo è incluso nella lingua?


5
Penso che la domanda corretta sia, perché no?
Alberto Fernández,

5
perché non sembrano offrire alcun vantaggio, quindi perché includerli?
GSto

4
@HorusKol e prima che fossero implementati, non erano usati, quindi puoi vedere come erano inutilizzati e inutili solo una versione precedente. Devi anche fare e sostenere l'affermazione che il loro uso è in qualche modo un miglioramento per dire che sono utili.
Rein Henrichs,

6
@HorusKol Per niente specioso. È facile dimostrare la proposta di valore del martello. Questa domanda chiede a qualcuno di dimostrare la proposta di valore delle interfacce PHP, non solo di dichiarare che sono utili in modo argomentativo.
Rein Henrichs,

3
E ricorda che le interfacce non riguardano solo la digitazione. Un'interfaccia è un contratto che afferma che una classe di implementazione deve includere i metodi che definisce. Utile per cose come i motori plug-in.
Michael,

Risposte:


30

Il vantaggio principale delle interfacce in PHP è che le classi possono implementare più interfacce. Ciò consente di raggruppare le classi che condividono alcune funzionalità ma non condividono necessariamente una classe genitore. Alcuni esempi potrebbero includere la memorizzazione nella cache, l'output o l'accesso alle proprietà della classe in un certo modo.

Nel tuo codice, puoi verificare se una classe implementa una determinata interfaccia invece di controllare il nome della classe. Quindi, il tuo codice continuerà a funzionare quando vengono aggiunte nuove classi.

PHP fornisce alcune interfacce predefinite che possono tornare utili in varie situazioni: http://php.net/manual/en/reserved.interfaces.php .

MODIFICA - Aggiunta di un esempio

Se hai un'interfaccia chiamata MyInterface e stai lavorando con più oggetti di classi diverse che possono o meno condividere alcune funzionalità, le interfacce ti permettono di fare qualcosa del genere:

// Assume $objects is an array of instances of various classes
foreach($objects as $obj) {
 if($obj instanceof MyInterface) {
     $obj->a();
     $obj->b();
     $obj->c();
   }
}

23
In altre parole: "puoi ignorare completamente tutti i vantaggi dei linguaggi di tipo dinamico"
Kamil Tomšík,

11
@Kamil, ci penso più come essere in grado di sfruttare i vantaggi della digitazione statica senza subire gli inconvenienti quando non li vuoi.
Karl Bielefeldt,

9
sei serio? instanceof? if-then-if-then-if-then-then-as-the-time, non suona familiare? ah, sì, programmazione procedurale.
Kamil Tomšík,

23
@Kamil Tomšík Ancora un altro insulto alla lingua di PHP piuttosto che alle persone che lo usano in modo incompetente. PHP ha tutti gli strumenti per una completa programmazione orientata agli oggetti. Che tu li usi o meno dipende dal programmatore. Inoltre, non c'è nulla di sbagliato nella programmazione procedurale in sé e per sé.
Lotus Notes,

18
@Kamil - che strano, leggendo il tuo commento si potrebbe giungere alla conclusione che non ci sono if-in in OOP e che, in qualche modo, magicamente - le cose funzionano. Wow.
Michael JV,

23

PHP è tipicamente diffuso, ma può essere fortemente tipizzato su cose come i parametri del metodo.

Considera il seguente esempio:

interface Car { function go(); }

class Porsche { function go() {} }

function drive(Car $car) {}

$porsche = new Porsche();

drive($porsche);

Il codice sopra riportato produrrebbe:

L'argomento 1 passato a drive () deve implementare l'interfaccia Car, istanza di Porsche fornita


1
Certo, è troppo male. nullTuttavia, puoi avere un valore predefinito per il parametro.
Emanuil Rusev,

5
ma se driverichiede un Carpassaggio, il passaggio nullnon sarebbe comunque molto utile ...
HorusKol,

7
Non passare mai null. Usa un oggetto "Caso speciale" (Google per la spiegazione di Martin Fowler).
Martin Blore,

2
@Renesis Se si imposta il valore predefinito su null, è possibile passare null in metodi con suggerimenti di tipo. (CAR $ car = null) ti permetterebbe di chiamare questo metodo con null come argomento. Questa sarebbe comunque una pratica piuttosto sciocca. Perché mai vorresti essere in grado di farlo?
dqhendricks,

2
Esempio concreto: function addView($name, Template $template, SecurityMode $securityMode = null, $methodName = null);potresti avere un $methodNamema no $securityMode.
Nicole,

7

Le interfacce consentono di implementare il principio aperto-chiuso, mantenere una base di codice liberamente accoppiata e implementare molti dei migliori modelli di progettazione OOP.

Ad esempio, se una classe accetta un'altra classe come argomento:

class A {

    public function __construct(B $class_b) {
        // use class b
        $class_b->run();
    }
}

La tua classe A e la classe B ora hanno un accoppiamento stretto e la classe A non può usare nessun'altra classe tranne B. Il suggerimento sul tipo assicura che tu abbia il tipo corretto di argomento, ma ora ha cementato la relazione tra A e B.

Diciamo che vuoi che la classe A sia in grado di usare tutti i tipi di classi che hanno un metodo run (). Questo è fondamentalmente (ma non del tutto) il modello di progettazione COMMAND. Per risolvere, dovresti invece digitare hint usando un'interfaccia anziché una classe concreta. B implementerebbe tale interfaccia e verrà accettato come argomento per la classe A. In questo modo la classe A può accettare qualsiasi classe che utilizza tale interfaccia come argomento per il suo costruttore.

Questo tipo di codifica viene utilizzato nella maggior parte dei modelli di progettazione OOP e consente di modificare molto più facilmente il codice in un secondo momento. Questi fanno parte dei fondamenti della programmazione AGILE.


1
O qualsiasi sottoclasse di B
Mez,

7

@pjskeptic ha una buona risposta e @Kamil Tomšík ha un buon commento su quella risposta.

La cosa grandiosa di linguaggi tipicamente dinamici come PHP è che puoi provare a usare metodi su oggetti e non ti grideranno a meno che il metodo non sia lì.

Il problema con linguaggi tipicamente dinamici come PHP è che puoi provare a usare metodi su oggetti e ti urlerà quando il metodo non è lì.

Le interfacce aggiungono un modo conveniente di chiamare metodi su un oggetto sconosciuto ed essere certi che i metodi ci siano (non che siano necessariamente corretti o funzioneranno). Non è una parte necessaria di una lingua, ma rende la codifica più conveniente. Consente agli sviluppatori OOP fortemente tipizzati di scrivere codice PHP fortemente tipizzato, che può quindi lavorare a fianco del codice PHP liberamente scritto da un altro sviluppatore PHP.

una funzione come:

foo( IBar $bar )
{
  $baz = $bar->baz();
  ...
}

è più conveniente di:

foo( $bar )
{
  if ( method_exists( $bar, 'baz' ) )
  {
    $baz = $bar->baz();
  }
  else
  {
    throw new Exception('OMGWTF NO BAZ IN BAR!');
  }
  ...
}

e il codice IMHO semplice e leggibile è un codice migliore.


1
quello che fai invece non è semplicemente controllare il metodo, arrestare e masterizzare quando qualcuno chiama la tua funzione con i dati sbagliati. Non è un tuo problema se qualcuno usa la tua funzione in modo sbagliato.
Raynos,

no esattamente - il tuo esempio è un incubo per chiunque voglia passare qualsiasi "anatra" dinamica, come proxy, adattatore, decoratore ecc.
Kamil Tomšík,

1
@Kamil? Come mai. Un proxy sarebbe una classe wrapper per qualcosa che non implementa l'interfaccia per consentirne l'utilizzo con questa funzione.
Tylermac,

@tylermac proxy dinamico usando __call () - e se __call è l'unico metodo lì, semplicemente non può implementare IBar, il che significa che non puoi passarlo a foo (IBar $ bar)
Kamil Tomšík

5

Sono completamente inutili se sei un papero, in realtà quando fai la tipografia, è piuttosto fastidioso lavorare con librerie / framework che usano qualsiasi tipo di suggerimento.

Questo vale anche per tutti i tipi di meta-programmazione dinamica (metodi magici).


3

PHP non è vagamente o fortemente, ma digitato in modo dinamico .

A proposito di interfacce, la prima cosa che dovresti chiederti è: quali sono i maggiori vantaggi delle interfacce?

In OOP, le interfacce non riguardano solo i tipi, ma anche il comportamento.

Poiché PHP ha anche una funzione di suggerimento del tipo , puoi usare le interfacce proprio come faresti in un linguaggio oo puro, come Java.

interface File
{
    public function getLines();
}

CSVFile implements File
{
    public function getLines()
    {}
}

XMLFile implements File 
{
    public function getLines()
    {}
}

JSONFile implements File 
{
    public function getLines()
    {}
}

class FileReader
{
    public function read(File $file)
    {
        foreach($file->getLines() as $line)
        {
            // do something
        }
    }
}

Con l'implementazione dell'interfaccia PHP, puoi anche creare simulazioni per le classi astratte usando PHPUnit - e questa è una caratteristica infernale:

public function testSomething()
{
    $mock = $this->getMockForAbstractClass('File');

    $mock->expects($this->once())
         ->method('getLines')
         ->will($this->returnValue(array()));

    // do your assertions
}

Quindi, fondamentalmente, puoi avere un'applicazione compatibile SOLID in PHP usando le funzionalità del linguaggio, una delle quali è l'interfaccia.


0

Le interfacce sono utili per l'iniezione di dipendenza molto più che per il calcestruzzo. Come esempio barebone:

interface Istore { 
  public function save(); 
}

class Article_DB implements Istore 
{ 
  public function save($data) 
  {
    // do save to format needed.
  } 
}

class Article
{
   private $content;

   public function content($content)
   {
     $this->content = $content;
   }

   public function save(Istore $store)
   {
     $store->save($this->content);
   }
}

$article = new Article();
$article->content('Some content');

$store = new Article_DB();
$article->save($store);

Ora dì se le tue esigenze cambiano e vuoi salvare in un pdf. È possibile creare una nuova classe a tale scopo invece di inquinare la classe Article.

class Article_PDF implements Istore 
{ 
  public function save($data) 
  {
    // do save to format needed.
  } 
}


$article = new Article();
$article->content('Some content');

$store = new Article_PDF();
$article->save($store);

La classe Article ora ha un contratto che le classi che utilizza per salvare devono implementare l'interfaccia Istore. Non gli importa dove salva o come salva.


-1

È possibile fornire oggetti reali "falsi" che implementano l'interfaccia. È quindi possibile testare l'unità di una parte del codice senza richiedere server, file system, socket, database, ecc.


-3

Molte persone probabilmente mi odieranno per aver risposto in questo modo, ma la soluzione ai tuoi problemi di battitura può essere facilmente risolta con PHP. Sì, PHP è tipizzato in modo approssimativo, quindi i tipi sono assunti per impostazione predefinita, il che può causare alcuni problemi, specialmente nelle operazioni di confronto che è il problema della maggior parte delle persone. Detto questo, PHP può essere altrettanto rigoroso di qualsiasi linguaggio fortemente tipizzato se si inserisce ciò che si sta utilizzando nel tipo che si desidera che sia, e quindi si utilizzano operatori di confronto bit a bit. Ecco l'esempio più semplice che mi viene in mente di quello che sto dicendo:

$ myVar = (int) 0; $ myOtherVar = '0';

il confronto ($ myVar == $ myVar) equivarrebbe a (bool) vero

ma il confronto ($ myVar === $ myVar) equivarrebbe a (bool) falso proprio come qualsiasi confronto "tipizzato"

Vorrei davvero che gli sviluppatori smettessero di discutere di queste cose, se hai un problema con il modo in cui PHP funziona o vai a programma in Java e vivi e lascia vivere, o usalo nel modo in cui farà quello che vuoi .. Qual è il vantaggio della puttana per te? Ti dà una scusa per andare in giro tutto il giorno? Ti fanno sembrare migliore di qualcun altro? Bene, è bello che tu ti senta così tanto su te stesso che sei disposto a far apparire male qualcun altro, ma in realtà è la tua preferenza e forzare le tue convinzioni su qualcuno rende semplicemente il codice in un modo in cui non si sentono a proprio agio nel causare tre cose:

1) Ti codificheranno a modo tuo ma "disordinato" secondo i tuoi standard (pensi, hai mai visto un programmatore Java creare il suo primo programma PHP o viceversa? Sarà allo stesso modo cambiare la loro metodologia o forse anche peggio.)

2) Troverai qualcos'altro di cui lamentarti

3) Probabilmente impiegherà più tempo a produrre. E forse ti farà apparire meglio a breve termine, ma il team nel suo complesso avrà un aspetto peggiore (ricorda che potresti codificare più lentamente di qualcun altro e non è necessariamente male finché il team incontra i risultati in un periodo di tempo ragionevole, ma forzare le tue abitudini su qualcuno che si è comportato in genere un po 'più velocemente può finire per rallentare così l'intero team, quindi apparire peggio in un flusso di lavoro molto impegnativo)

Personalmente preferisco scrivere codice procedurale PHP anche se posso, e ho, scritto programmi completi usando OOP in poche lingue diverse. Detto questo, ho visto un buon codice OOP e un cattivo codice OOP, e un buon codice procedurale e un cattivo codice procedurale per quella materia ... Non ha davvero nulla a che fare con la pratica, ma con le abitudini che usi e anche allora, molte cose sono i miei sentimenti interpretati ... ciò non significa che parlerò male di quegli sviluppatori o che mi vanto di BS "la mia strada è la cosa migliore", è giusto per me e la compagnia per cui lavoro è carina felice del mio lavoro e ne vado fiero. Ci sono motivi per cui dovrebbe essere stabilito uno standard, ma ciò che includi nello standard che scegli è MOLTO importante ... Grazie per avermi permesso di togliermelo dal petto. Vi auguro una buona giornata.


-4
  1. Le interfacce fanno parte del paradigma OOP. Quindi è molto utile in molti casi quando si cerca di realizzare parti orientate agli oggetti o il proprio sistema.
  2. Così. Perchè no? ;-)

Esempi: è necessario memorizzare nella cache i dati. Come? Esistono molti motori diversi per la memorizzazione nella cache, qual è il migliore? A chi importa se hai un livello astratto che ha un'interfaccia ICacheDriver con una serie di metodi come key, get, put, clear, ecc. Basta implementare ciò di cui hai bisogno nel progetto corrente e cambiarlo quando ne hai bisogno. O semplice utilizzo di toString. Hai un set di diversi oggetti visualizzabili. Devi solo implementare l'interfaccia Stringable (che descrive il metodo toString [non ci sono davvero interfacce come quella in PHP, ma per esempio]) e interagire su tutto il tuo oggetto con (stringa) $ obj. C'è tutto quello che devi fare invece di switch (true) {case $ obj isntanceof A1: "do 1"; rompere; ...}

Semplice. Quindi non c'è dubbio "Perché?". C'è "come usarlo meglio?". ;-) In bocca al lupo.


-5

La mia ipotesi

PHP è utilizzato da molti programmatori entry level, i programmatori entry level sono tenuti a java al college.

Dopo il corso di Programmazione 101 iniziano a tormentare Zend, vogliono funzionalità Java perché è così che è stato loro insegnato a pensare, è difficile pensare ai tuoi termini (o capire la tipizzazione delle anatre) quando hai solo 20 anni.

Zend è pragmatico, è più facile aggiungere la funzione piuttosto che fingere che siano sempre finiti.
Questo acquista anche più utenti invece di farli partire, quindi deve essere buono.

Un'altra istanza di questo processo? Le persone appena uscite dai corsi .NET e Java vogliono anche Frameworks of Foundation Classes , che si preoccupano fino a quando Zend non espone Zend Framework . Questo acquista ancora più utenti. E ancora e ancora ...

(l'unica caratteristica linguistica per cui il team PHP è noto per aver lottato , nel corso degli anni, è goto)


Nella mia visione, PHP12probabilmente avrò tutte le caratteristiche di sintassi del mondo (spero che non ottenga un runtime di livello di astrazione, duro, dato che è quello che ha ucciso perl) con un occhiolino ai paradigmi funzionali e di tipo di dati, e ancora no goto.
ZJR,

"è difficile, quando hai solo 20 anni" Come potrebbe l'età avere qualcosa a che fare con la comprensione di questi concetti?
Evicatos,

I programmi per i liceali di @Evicatos, ma di solito hanno cattivi insegnanti, cattive convenzioni di denominazione e producono macchie non mantenibili. Imparano a programmare bene quando iniziano il college, ci vogliono un paio d'anni per farlo andare avanti. Poi iniziano a divergere dalle lingue dure, benedette dall'industria, acclamate dal punto di vista accademico, che sono state insegnate in quei primi anni e si rivolgono a, più pragmatiche, dattiloscritte. Credo che questo sia un bushido che molti programmatori condividono. Inoltre, questo potrebbe non riflettere la tua esperienza, potresti essere un esperto autodidatta. In tal caso, mostraci la strada.
ZJR,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.