Alcune risposte qui sono molto generiche affermando che un interface
è un contratto. È difficile dire che sono un contratto quando non c'è spazio per interfacce e classi in PHP. Quindi è impossibile far rispettare il contratto. Non c'è nulla che impedisca a uno sviluppatore di creare un'istanza di una classe e di ignorare l'interfaccia. Quindi la descrizione del contratto non è chiara per gli sviluppatori che non hanno mai usato Java o C ++.
Quindi di cosa si tratta?
Il tuo esempio non è molto buono. UserInterface
in AbstractUserClass
in GenericUserClass
in realtà non mostra i benefici di ciò che sta accadendo. Quindi permettimi di espanderlo un po '.
Perché abbiamo interfacce, perché un oggetto può implementare più interfacce. Pensa a un'interfaccia non come metodi ma come comportamento definito per una classe. L'interfaccia dice "Posso comportarmi come un utente ". Non importa come il codice raggiunge questo. Solo che supporta questa interfaccia.
La chiave per un buon design dell'interfaccia non è la creazione di interfacce multiuso. Lascia che ogni interfaccia definisca un singolo comportamento. Ciò rende molto più facile creare classi a scopo singolo che funzionano su questi tipi di oggetti. Invece di avere un UserInterface
potresti espandere quello per includere AdminInterface
, AuthenticatedUserInterface
e UserPermissionsInterface
. Quindi, più avanti nel tuo codice, puoi chiedere a un oggetto se supporta AdminInterface
e, in tal caso, quell'utente è un amministratore.
Perché abbiamo classi astratte?
Interfacce, interfacce, interfacce ovunque ... Uno degli svantaggi nell'uso delle interfacce è che un'interfaccia non implementa assolutamente alcun codice. Per ogni interfaccia un programmatore deve implementare almeno una classe. Un buon framework che utilizza interfacce ti fornirà un'ampia gamma di classi astratte già implementate che ti danno un punto di partenza per l'utilizzo di tali interfacce. Un cattivo framework è uno che richiede molte interfacce e non ti dà nulla da cui partire.
Evita la classe astratta super che implementa molte interfacce e fornisce la maggior parte delle funzionalità per tali interfacce. È anche pesantemente ereditato da molte altre classi.
Quello che vuoi sono piccole classi astratte che implementano un'interfaccia da diverse prospettive. Potresti voler creare un paio di classi che implementano UserInterface
come AbstractInvalidUser
, AbstractAnonymousUser
o AbstractAuthenticatedUser
. In seguito potresti dover utilizzare Facebook per accedere a un utente. Puoi quindi creare un FaceBookUser
che estende AbstractAuthenticatedUser
. Ora è chiaro cosa fa ogni classe astratta, ma tutti implementano il UserInterface
.
Quindi ora la grande domanda "Dove vanno a finire tutti i metodi?"
La chiave per creare codice sorgente gestibile è ridurre sempre le dipendenze fino alla loro parte più piccola. Ciò significa che non vuoi che il codice sorgente utilizzi FaceBookUser
quando tutto ciò che sta facendo è visualizzare il nome dell'utente corrente. Se tutto nel codice sorgente utilizza FaceBookUser
, è difficile spostare quella classe in un'altra cartella o rinominare quella classe. Per te è più semplice utilizzare UserInterface
per visualizzare il nome di un utente e ora tutto quel codice sorgente non interessa se si tratta di Facebook, Google+ o del tuo accesso. La dipendenza è ridotta perché l'interfaccia è semplice e con un solo scopo.
Perché le interfacce separano il codice dall'implementazione dell'interfaccia. Al tuo altro codice non interessa se l'oggetto corrente è una classe wrapper, una classe delegate, una classe super pesante o solo una classe semplice. Per quanto riguarda il codice, è solo un riferimento UserInterface
.
Le interfacce sono strumenti che consentono di creare codice di gestione. Posiziona i metodi nelle interfacce in modo da non creare dipendenze tra le classi. Puoi creare una separazione dalla tua dipendenza creando più di una interfaccia.
Questo è ciò che le persone intendono quando lo chiamano "contratto".