Ci sono molte ragioni per cui Java ha il proprio costrutto per l'ereditarietà multipla, cioè con interface
e abstract
classi. Eccone tre che posso pensare:
Riduce il codice boilerplate (cioè le funzioni pure virtuali)
Nelle lingue che non hanno il costrutto interface
, devi fare molta codifica di tipo standard. Considerare in C ++ è necessario creare una classe che abbia pure funzioni virtuali:
class MyInterface
{
public:
virtual void show() = 0;
virtual int number() = 0;
};
class ConcreteImpl : public MyInterface
{
public:
void show()
{
cout << "Concrete Impl here";
}
int number()
{
return 1337;
}
};
L'equivalente in Java sarebbe meno dettagliato, principalmente perché i metodi sono funzioni virtuali (sostituibili). Ed è più evidente che una delle risorse è l'interfaccia.
interface MyInterface {
void show();
int number();
}
class ConcreteImpl implements MyInterface {
public void show() {
System.out.println("Concrete Impl here");
}
public int number() { return 1337; }
}
Java consente una classe con pura virtualità mista e implementazione, con la parola chiave abstract
.
Limita il problema "ereditarietà del diamante"
Uno dei problemi associati all'ereditarietà multipla è il peloso problema dell'eredità del diamante . Considera se hai un linguaggio che consente questa catena di classi in un linguaggio come C ++:
PensaaSuperBaseClass
chehadueimplementatiBaseClass
,entrambiimplementandoilmetododiSuperBaseClass
comefunzionivirtuali.AsuavoltaentrambiBaseClass
sonoimplementatidallaclasseMyImplementation
.Consideracosasuccederàsechiamisuper()
inMyImplementation.draw()
?Nonèsemprechiarocosasuccederà,ancheinC++,glisviluppatorichelohannoprogettatositroverannoinunastranasessionedidebug.
Nonc'ènientedisbagliatoinparticolarenell'ereditarietàdeidiamanti,quindiperevitareiproblemidichiamareilsuper-metodo,deviprogettarliusandopurefunzionivirtualiodisegnandoliinmodopiùintelligente.InJava,poichétuttiimetodisonovirtualiperimpostazionepredefinita,sièvincolatidalfattocheèpossibileeseguirel'ereditarietàmultiplasoloconinterface
spoichénoncontengonoalcunaimplementazione(conlaparolachiaveimplements
).Altreclassi,ancheabstract
,possonoessereereditatesolo(conlaparolachiaveextends
).
Glisviluppatoristagionatiutilizzavanogiàleinterfaccecomeconcetto(circa1995)
Seseientratoin Design Patterns by GoF , noterai che fanno molto affidamento sulle interfacce per progettare sistemi estensibili. In effetti uno dei principi di Design Patterns è:
"Program to an 'interface', not an 'implementation'." (Gang of Four 1995:18)
L'interfaccia nel senso di GoF significa che dovresti programmare verso una superclasse piuttosto che l'implementazione. Un esempio potrebbe essere che dovresti preferire digitare la tua variabile su Collection<T>
, Iterable<T>
o List<T>
anziché ArrayList<T>
in Java se gli unici metodi che usi sull'oggetto lo ripetono. Un esempio di modello da GoF sarebbe il modello di strategia in cui il contesto non ha bisogno di conoscere la strategia esatta che viene data a esegui, ma eseguirà il set, indipendentemente da cosa fosse.