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?
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?
Risposte:
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();
}
}
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
null
Tuttavia, puoi avere un valore predefinito per il parametro.
drive
richiede un Car
passaggio, il passaggio null
non sarebbe comunque molto utile ...
function addView($name, Template $template, SecurityMode $securityMode = null, $methodName = null);
potresti avere un $methodName
ma no $securityMode
.
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.
@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.
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).
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.
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.
È 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.
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.
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.
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
)
PHP12
probabilmente 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
.