Perché non esiste un’eredità multipla in Java, ma l’implementazione di più interfacce è consentita?

Java non consente l’ereditarietà multipla, ma consente l’implementazione di più interfacce. Perché?

Perché le interfacce specificano solo ciò che sta facendo la class, non come lo sta facendo.

Il problema con l’ereditarietà multipla è che due classi possono definire diversi modi di fare la stessa cosa, e la sottoclass non può scegliere quale scegliere.

Uno dei miei istruttori del college mi ha spiegato in questo modo:

Supponiamo che io abbia una class, che è un tostapane e un’altra class, che è NuclearBomb. Entrambi potrebbero avere un’impostazione “oscurità”. Entrambi hanno un metodo on (). (Uno ha un off (), l’altro no.) Se voglio creare una class che sia una sottoclass di entrambi questi … come puoi vedere, questo è un problema che potrebbe davvero esplodere in faccia qui .

Quindi uno dei problemi principali è che se hai due classi genitore, potrebbero avere implementazioni diverse della stessa funzione o forse due diverse caratteristiche con lo stesso nome, come nell’esempio del mio istruttore. Quindi devi decidere quale sarà la tua sottoclass. Ci sono modi per gestire questo, certamente – C ++ lo fa – ma i progettisti di Java sentivano che ciò avrebbe reso le cose troppo complicate.

Con un’interfaccia, però, stai descrivendo qualcosa che la class è in grado di fare, piuttosto che prendere in prestito il metodo di un’altra class per fare qualcosa. È molto meno probabile che più interfacce causino conflitti complessi che devono essere risolti rispetto a più classi parent.

Poiché l’ereditarietà è sovrautilizzata anche quando non si può dire “hey, quel metodo sembra utile, estenderò anche quella class”.

public class MyGodClass extends AppDomainObject, HttpServlet, MouseAdapter, AbstractTableModel, AbstractListModel, AbstractList, AbstractMap, ... 

L’implementazione di più interfacce è molto utile e non causa molti problemi agli implementatori linguistici né ai programmatori. Quindi è permesso. L’ereditarietà multipla, sebbene sia anche utile, può causare seri problemi agli utenti (temuto diamante della morte ). E molte cose che fai con l’ereditarietà multipla possono anche essere fatte per composizione o usando classi interne. Quindi l’eredità multipla è proibita perché porta più problemi che guadagni.

Per lo stesso motivo, C # non consente l’ereditarietà multipla ma consente di implementare più interfacce.

La lezione appresa da C ++ con ereditarietà multipla è stata che ha portato a più problemi di quanti ne valesse.

Un’interfaccia è un contratto di cose che la tua class deve implementare. Non ottieni alcuna funzionalità dall’interfaccia. L’ereditarietà ti consente di ereditare la funzionalità di una class genitore (e in ereditarietà multipla, che può diventare estremamente confusa).

La possibilità di utilizzare più interfacce consente di utilizzare modelli di progettazione (come Adattatore) per risolvere gli stessi tipi di problemi che è ansible risolvere utilizzando l’ereditarietà multipla, ma in modo molto più affidabile e prevedibile.

Si dice che lo stato degli oggetti sia riferito ai campi in esso contenuti e diverrebbe ambiguo se venissero ereditate troppe classi. Ecco il link

http://docs.oracle.com/javase/tutorial/java/IandI/multipleinheritance.html

Java supporta l’ereditarietà multipla solo attraverso le interfacce. Una class può implementare qualsiasi numero di interfacce ma può estendere solo una class.

L’ereditarietà multipla non è supportata perché porta a un problema di diamante mortale. Tuttavia, può essere risolto ma conduce a un sistema complesso in modo che l’ereditarietà multipla sia stata eliminata dai fondatori di Java.

In un white paper intitolato “Java: an Overview” di James Gosling nel febbraio 1995 ( link ) fornisce un’idea sul perché l’ereditarietà multipla non è supportata in Java.

Secondo Gosling:

“JAVA omette molte caratteristiche del C ++ usate raramente, scarsamente comprese e confuse che nella nostra esperienza portano più dolore che beneficio. Questo principalmente consiste nell’overloading dell’operatore (sebbene abbia sovraccarico di metodo), ereditarietà multipla e estese coercizioni automatiche.”

Dato che questo argomento non è vicino pubblicherò questa risposta, spero che questo aiuti qualcuno a capire perché java non consente l’ereditarietà multipla.

Considera la seguente class:

 public class Abc{ public void doSomething(){ } } 

In questo caso la class Abc non estende nulla di giusto? Non così veloce, questa class implicita estende la class Object, class base che consente a tutto ciò che funziona in java. Tutto è un object.

Se provate ad usare la class sopra vedrete che il vostro IDE vi permette di usare metodi come: equals(Object o) , toString() , etc, ma non avete dichiarato quei metodi, sono venuti dalla class base Object

Potresti provare:

 public class Abc extends String{ public void doSomething(){ } } 

Questo va bene, perché la tua class non implicherà l’estensione Object ma estenderà String perché lo hai detto. Considera la seguente modifica:

 public class Abc{ public void doSomething(){ } @Override public String toString(){ return "hello"; } } 

Ora la tua class restituirà sempre “ciao” se chiami toString ().

Ora immagina la seguente class:

 public class Flyer{ public void makeFly(){ } } public class Bird extends Abc, Flyer{ public void doAnotherThing(){ } } 

Ancora una volta la class Flyer implicita estende Object che ha il metodo toString() , qualsiasi class avrà questo metodo poiché tutti estendono Object indirettamente, quindi, se si chiama toString() da Bird , quale toString() java dovrebbe usare? Da Abc o Flyer ? Ciò avverrà con qualsiasi class che tenta di estendere due o più classi, per evitare questo tipo di “collisione di metodo” hanno costruito l’idea di interfaccia , in pratica si potrebbe pensare che siano una class astratta che non estende Object indirettamente . Poiché sono astratti , dovranno essere implementati da una class, che è un object (non è ansible instanciare un’interfaccia da solo, devono essere implementati da una class), quindi tutto continuerà a funzionare correttamente.

Per differenziare le classi dalle interfacce, le implementazioni delle parole chiave erano riservate solo per le interfacce.

Puoi implementare qualsiasi interfaccia che ti piace nella stessa class poiché non estende nulla per impostazione predefinita (ma potresti creare un’interfaccia che estende un’altra interfaccia, ma ancora una volta, l’interfaccia “padre” non estenderebbe Object “), quindi un’interfaccia è solo un’interfaccia e non soffriranno di ” metodi colazioni firma “, se lo fanno il compilatore ti invierà un avvertimento e dovrai solo cambiare la firma del metodo per risolverlo (firma = nome metodo + parametri + tipo di ritorno) .

 public interface Flyer{ public void makeFly(); // <- method without implementation } public class Bird extends Abc implements Flyer{ public void doAnotherThing(){ } @Override public void makeFly(){ // <- implementation of Flyer interface } // Flyer does not have toString() method or any method from class Object, // no method signature collision will happen here } 

È ansible trovare una risposta precisa per questa query nella pagina di documentazione di Oracle relativa all’ereditarietà multipla

  1. Multiple inheritance of state: possibilità di ereditare campi da più classi

    Uno dei motivi per cui il linguaggio di programmazione Java non consente di estendere più di una class è di evitare i problemi dell’ereditarietà multipla dello stato, che è la possibilità di ereditare i campi da più classi

    Se è consentita l’ereditarietà multipla e quando si crea un object creando un’istanza di quella class, quell’object erediterà i campi da tutte le superclassi della class. Causerà due problemi

    1. Cosa succede se i metodi oi costruttori di diverse super classi istanziano lo stesso campo?
    2. Quale metodo o costruttore avrà la precedenza?
  2. Eredità multipla di implementazione: possibilità di ereditare definizioni di metodo da più classi

    Problemi con questo approccio: denominare i conflitti e l’ ambiguità . Se una sottoclass e una superclass contengono lo stesso nome (e firma) del metodo, il compilatore non può determinare quale versione richiamare.

    Ma java supporta questo tipo di ereditarietà multipla con metodi predefiniti , che sono stati introdotti dalla versione Java 8. Il compilatore Java fornisce alcune regole per determinare quale metodo predefinito utilizza una determinata class.

    Fare riferimento al post SE in basso per ulteriori dettagli sulla risoluzione del problema del diamante:

    Quali sono le differenze tra classi astratte e interfacce in Java 8?

  3. Multiple inheritance of type: capacità di una class di implementare più di una interfaccia.

    Poiché l’interfaccia non contiene campi mutabili, non ci si deve preoccupare dei problemi derivanti dall’eredità di stato multipla qui.

Perché un’interfaccia è solo un contratto. E una class è in realtà un contenitore per i dati.

Prendiamo ad esempio il caso in cui la Classe A ha un metodo getSomething e la class B ha un metodo getSomething e la class C estende A e B. Cosa accadrebbe se qualcuno chiamasse C.getSomething? Non c’è modo di determinare quale metodo chiamare.

In pratica, le interfacce specificano solo i metodi che una class di implementazione deve contenere. Una class che implementa interfacce multiple significa semplicemente che la class deve implementare i metodi da tutte quelle interfacce. Whci non comporterebbe alcun problema come descritto sopra.

Si consideri uno scenario in cui Test1, Test2 e Test3 sono tre classi. La class Test3 eredita le classi Test2 e Test1. Se le classi Test1 e Test2 hanno lo stesso metodo e la si chiama dall’object class figlio, ci sarà un’ambiguità per chiamare il metodo di Test1 o Test2 ma non c’è tale ambiguità per l’interfaccia come nell’interfaccia, nessuna implementazione è presente.

Java non supporta ereditarietà multipla, multipath e ibrida a causa di problemi di ambiguità:

  Scenario for multiple inheritance: Let us take class A , class B , class C. class A has alphabet(); method , class B has also alphabet(); method. Now class C extends A, B and we are creating object to the subclass ie, class C , so C ob = new C(); Then if you want call those methods ob.alphabet(); which class method takes ? is class A method or class B method ? So in the JVM level ambiguity problem occurred. Thus Java does not support multiple inheritance. 

eredità multipla

Link di riferimento: https://plus.google.com/u/0/communities/102217496457095083679

Ad esempio due classi A, B aventi lo stesso metodo m1 (). E la class C estende sia A, B.

  class C extends A, B // for explaining purpose. 

Ora, la class C cercherà la definizione di m1. In primo luogo, cercherà in class se non lo trova, quindi controllerà la class dei genitori. Sia A che B hanno la definizione Quindi qui si verifica l’ambiguità che la definizione dovrebbe scegliere. Quindi, JAVA NON SUPPORTA UNA EREDITÀ MULTIPLA.

* Questa è una risposta semplice poiché sono un principiante in Java *

Considera che ci sono tre classi X , Y e Z

Quindi ereditiamo come X extends Y, Z E sia Y che Z hanno un metodo alphabet() con lo stesso tipo di ritorno e argomenti. Questo alphabet() metodo alphabet() in Y dice di visualizzare il primo alfabeto e l’alfabeto del metodo in Z dice visualizzare l’ultimo alfabeto . Quindi qui arriva l’ambiguità quando l’ alphabet() viene chiamato da X Se dice di visualizzare il primo o l’ ultimo alfabeto ??? Quindi java non supporta l’ereditarietà multipla. In caso di interfacce, considerare Y e Z come interfacce. Quindi entrambi conterranno la dichiarazione di metodo alphabet() ma non la definizione. Non dirà se visualizzare il primo alfabeto o l’ultimo alfabeto o altro ma semplicemente dichiarerà un metodo alphabet() . Quindi non c’è motivo di sollevare l’ambiguità. Possiamo definire il metodo con qualsiasi cosa vogliamo all’interno della class X

Quindi in una parola, nella definizione delle interfacce viene fatto dopo l’implementazione, quindi nessuna confusione.