it-swarm.com.de

Warum ist Mehrfachvererbung in Java oder C # nicht zulässig?

Ich weiß, dass Mehrfachvererbung in Java und C # nicht zulässig ist. Viele Bücher sagen nur, dass Mehrfachvererbung nicht erlaubt ist. Es kann jedoch mithilfe von Schnittstellen implementiert werden. Es wird nichts darüber diskutiert, warum es nicht erlaubt ist. Kann mir jemand genau sagen, warum es nicht erlaubt ist?

100

Die kurze Antwort lautet: Weil sich die Sprachdesigner nicht entschieden haben.

Grundsätzlich schien es, dass sowohl die .NET- als auch die Java-Designer keine Mehrfachvererbung zuließen, weil sie der Meinung waren, dass das Hinzufügen von MI den Sprachen zu viel Komplexität hinzufügte und gleichzeitig zu wenig Nutzen brachte.

Für mehr Spaß und eine gründliche Lektüre gibt es einige Artikel im Internet mit Interviews mit einigen der Sprachdesigner. Für .NET hat beispielsweise Chris Brumme (der bei MS im Bereich CLR gearbeitet hat) die Gründe dafür genannt, warum sie sich entschieden haben:

  1. Unterschiedliche Sprachen haben tatsächlich unterschiedliche Erwartungen, wie MI funktioniert. Zum Beispiel, wie Konflikte sind gelöst und ob doppelte Basen sind zusammengeführt oder überflüssig. Bevor wir können MI in der CLR implementieren, müssen wir tun eine Übersicht aller Sprachen, Abbildung aus den gemeinsamen Begriffen heraus und entscheiden wie man sie in einer .__ ausdrückt. sprachneutral. Wir würden auch müssen entscheiden, ob MI in .__ gehört. der CLS und was das für .__ bedeuten würde. Sprachen, die dieses Konzept nicht wollen (vermutlich VB.NET zum Beispiel). Von Natürlich sind wir in diesem Geschäft als Common Language Runtime, aber wir Ich bin nicht dazu gekommen, es für MI zu tun. noch.

  2. Die Anzahl der Orte, an denen MI wirklich geeignet ist, ist tatsächlich ziemlich klein. In vielen Fällen sind mehrere Schnittstellenvererbung kann den Job erhalten stattdessen gemacht. In anderen Fällen können Sie können Kapselung und .__ verwenden. Delegation. Wenn wir ein .__ hinzufügen würden. etwas anderes Konstrukt, wie Mixins, wäre das eigentlich mehr mächtig?

  3. Die Mehrfachimplementierungsvererbung fügt dem .__ viel Komplexität hinzu. Implementierung. Diese Komplexität Auswirkungen Guss, Layout, Versand, Feldzugang, Serialisierung, Identität Vergleiche, Überprüfbarkeit, Reflexion, Generika und wahrscheinlich viele andere Orte.

Sie können den vollständigen Artikel hier lesen.

Für Java können Sie diesen Artikel lesen:

Die Gründe für das Auslassen mehrerer Vererbung aus der Java-Sprache Meistens stammen sie aus dem "einfachen, objektorientierten und vertrauten" Ziel. Als ein einfache Sprache, Javas Schöpfer wollte eine Sprache, die die meisten Entwickler könnte ohne umfangreiche Ausbildung. Zu diesem Zweck arbeiteten sie an machen Sie die Sprache ähnlich wie C++ als möglich (vertraut) ohne zu tragen über die unnötige Komplexität von C++ (einfach). 

Nach Meinung der Designer sind mehrere Vererbung verursacht mehr Probleme und Verwirrung als es löst. Also schneiden sie Mehrfachvererbung aus der Sprache (genauso wie sie den Operator überladen). Die Designer sind umfangreich Die C++ - Erfahrung lehrte sie, dass Mehrfachvererbung war einfach nicht wert. die Kopfschmerzen.

133
Razzie

Mehrfachvererbung von Implementierung ist nicht zulässig. 

Das Problem ist, dass der Compiler/die Laufzeitumgebung nicht herausfinden kann, was zu tun ist, wenn Sie über eine Cowboy- und eine Artist-Klasse verfügen, die beide Implementierungen für die draw () - Methode haben und dann versuchen, einen neuen CowboyArtist-Typ zu erstellen. Was passiert, wenn Sie die draw () -Methode aufrufen? Liegt jemand tot auf der Straße oder haben Sie ein schönes Aquarell?

Ich glaube, es wird das Problem der doppelten Diamantvererbung genannt.

90
duffymo

Grund: Java ist aufgrund seiner Einfachheit sehr beliebt und einfach zu programmieren.

Was auch immer Java -Entwickler für Programmierer als schwierig und kompliziert empfinden, sie versuchten es zu vermeiden. Eine solche Eigenschaft ist die Mehrfachvererbung.

  1. Sie mieden Zeiger
  2. Sie vermieden die Mehrfachvererbung.

Problem mit Mehrfachvererbung: Diamantproblem.

Beispiel:

  1. Angenommen, Klasse A hat eine unterhaltsame Methode (). Klasse B und Klasse C stammen von Klasse A.
  2. Und beide Klassen B und C überschreiben die Methode fun ().
  3. Angenommen, Klasse D erbt sowohl Klasse B als auch Klasse C. (nur Annahme)
  4. Erstellen Sie ein Objekt für die Klasse D.
  5. D d = neues D ();
  6. und versuche auf d.fun () zuzugreifen; => Wird es den Spaß der Klasse B () oder den Spaß der Klasse C () nennen?

Dies ist die Mehrdeutigkeit, die im Diamantproblem besteht.

Es ist nicht unmöglich, dieses Problem zu lösen, aber es führt beim Lesen zu mehr Verwirrung und Komplexität für den Programmierer. Es verursacht mehr Probleme als es zu lösen versucht.

Anmerkung: Sie können jedoch auf jede Weise die Mehrfachvererbung indirekt über Schnittstellen implementieren.

19
user1923551

Weil Java eine andere Designphilosophie hat als C++. (Ich werde C # hier nicht diskutieren.)

Bei der Entwicklung von C++ wollte Stroustrup nützliche Funktionen einschließen, unabhängig davon, wie sie missbraucht werden könnten. Es ist möglich, sich mit Mehrfachvererbung, Überladen von Operatoren, Vorlagen und verschiedenen anderen Funktionen zu beschäftigen, aber es ist auch möglich, einige sehr gute Dinge mit ihnen zu tun.

Die Java-Designphilosophie besteht darin, Sicherheit in Sprachkonstrukten zu betonen. Das Ergebnis ist, dass es Dinge gibt, die viel unpraktischer zu machen sind, aber Sie können viel sicherer sein, dass der Code, den Sie betrachten, das bedeutet, was Sie denken, dass es funktioniert.

Darüber hinaus war Java weitgehend eine Reaktion von C++ und Smalltalk, den bekanntesten OO -Sprachen. Es gibt viele andere OO - Sprachen (Common LISP war eigentlich die erste, die standardisiert wurde), mit verschiedenen OO - Systemen, die MI besser beherrschen.

Ganz zu schweigen davon, dass es durchaus möglich ist, MI in Java mithilfe von Schnittstellen, Komposition und Delegierung auszuführen. Es ist expliziter als in C++ und daher ungeschickter zu verwenden, bringt aber etwas, das Sie auf den ersten Blick eher verstehen.

Hier gibt es keine richtige Antwort. Es gibt verschiedene Antworten, und welche für eine gegebene Situation besser ist, hängt von den Anwendungen und individuellen Vorlieben ab.

13
David Thornley

Der Hauptgrund (wenn auch keineswegs der einzige) Grund, warum die Leute sich vom MI fernhalten, ist das sogenannte "Diamantproblem", das zu Mehrdeutigkeiten in Ihrer Implementierung führt. Dieser Wikipedia-Artikel bespricht es und erklärt es besser als ich könnte. MI kann auch zu komplexerem Code führen, und viele OO - Designer behaupten, dass Sie MI nicht benötigen. Wenn Sie es verwenden, ist Ihr Modell wahrscheinlich falsch. Ich bin nicht sicher, ob ich mit dem letzten Punkt einverstanden bin, aber die Dinge einfach zu halten, ist immer ein guter Plan.

12
Steve Haigh

In C++ war die mehrfache Vererbung bei unsachgemäßer Verwendung ein Hauptschmerz. Um diese bekannten Designprobleme zu vermeiden, wurde in modernen Sprachen (Java, C #) mehrere Schnittstellen "Vererbung" erzwungen.

8
inazaruk

Mehrfachvererbung ist

  • schwer zu verstehen 
  • schwer zu debuggen (wenn Sie beispielsweise Klassen aus mehreren Frameworks mit gleichnamigen Methoden zusammenstellen, können durchaus unerwartete Synergien auftreten)
  • einfach zu missbrauchen
  • nicht wirklich das nützlich
  • schwer zu implementieren, vor allem, wenn Sie es richtig machen wollen und effizient

Daher kann es als sinnvolle Entscheidung angesehen werden, not Multiple Inheritance in die Java-Sprache aufzunehmen.

8
mfx

Ein weiterer Grund ist, dass die einfache Vererbung trivial ist und keine Assembler-Anweisungen ausgibt (abgesehen von der Überprüfung der Kompatibilität der Typen, wo dies erforderlich ist). Wenn Sie Mehrfachvererbung hatten, müssen Sie herausfinden, wo in der Kindklasse ein bestimmter Elternteil beginnt. Leistung ist also sicherlich ein Vorteil (wenn auch nicht der einzige).

5
Blindy

Das dynamische Laden von Klassen erschwert die Implementierung von Mehrfachvererbung.

In Java haben sie die Komplexität der Mehrfachvererbung stattdessen durch die Verwendung von Einzelvererbung und Schnittstelle vermieden. .__ Die Komplexität der Mehrfachvererbung ist in einer Situation wie nachstehend erklärt sehr hoch

Raute Problem der Mehrfachvererbung. Wir haben zwei Klassen B und C, die von A erben. Nehmen wir an, B und C überschreiben eine vererbte Methode und stellen ihre eigene Implementierung bereit. Jetzt erbt D sowohl von B als auch von C, indem es mehrere Vererbungen durchführt. D sollte diese überschriebene Methode erben, kann jvm nicht entscheiden, welche überschriebene Methode verwendet wird?

In C++ werden virtuelle Funktionen verwendet, die behandelt werden müssen, und wir müssen dies explizit tun.

Dies kann durch die Verwendung von Schnittstellen vermieden werden, es gibt keine Methodenkörper. Schnittstellen können nicht instanziiert werden. Sie können nur von Klassen implementiert oder von anderen Schnittstellen erweitert werden.

4
sujith s

Früher (70er Jahre), als Computer Science mehr Wissenschaft und weniger Massenproduktion war, hatten die Programmierer Zeit, über gutes Design und gute Implementierung nachzudenken. Als Ergebnis hatten die Produkte (Programme) eine hohe Qualität (z. B. TCP/IP-Design) und Umsetzung). Heutzutage, wenn alle programmieren und die Manager die Spezifikationen vor Ablauf der Fristen ändern, sind subtile Probleme wie der, der im Wikipedia-Link von Steve Haigh beschrieben wird, schwer zu verfolgen. Daher ist die "Mehrfachvererbung" durch den Compilerentwurf begrenzt. Wenn Sie es mögen, können Sie C++ noch verwenden ... und haben alle Freiheiten, die Sie wollen :) 

4
Cata Lin

Ich nehme an, dass "Mehrfachvererbung in Java nicht zulässig ist" mit einer Prise Salz.

Mehrfachvererbung wird definiert, wenn ein "Typ" von mehreren "Typen" erbt. Schnittstellen werden auch als Typen klassifiziert, da sie Verhalten haben. Java hat also mehrere Vererbungen. Nur dass es sicherer ist.

4
Rig Veda

Tatsächlich tritt Mehrfachvererbung auf, wenn die geerbten Klassen dieselbe Funktion haben. dh der Compiler hat eine Verwirrung, die man wählen muss (Diamantproblem). Also in Java diese Komplexität entfernt und Schnittstelle gegeben, um die Funktionalität wie Mehrfachvererbung gegeben. Wir können Schnittstelle verwenden 

3
Jinu

Java hat ein Konzept, d. H. Einen Polymorphismus. Es gibt zwei Arten von Polymorphismus in Java. Es gibt Methodenüberladung und Methodenüberschreibung. Das Überschreiben von Methoden findet unter anderem in der Beziehung zwischen Super- und Unterklassen statt. Wenn wir ein Objekt einer Unterklasse erstellen und die Methode der Superklasse aufrufen, und wenn die Unterklasse mehr als eine Klasse umfasst, welche Superklassenmethode sollte aufgerufen werden?

Oder welcher Superklassenkonstruktor von super() aufgerufen wird, welcher Superklassenkonstruktor wird aufgerufen?

Diese Entscheidungen sind aufgrund der aktuellen Java-API-Funktionen nicht möglich. Daher ist in Java keine Mehrfachvererbung zulässig.

2
Abhay Kokate

Mehrfachvererbung ist in Java nicht direkt zulässig, über Schnittstellen jedoch zulässig.

Grund : 

Multiple Inheritance: Führt zu mehr Komplexität und Mehrdeutigkeit.

Schnittstellen: Schnittstellen sind vollständig abstrakte Klassen in Java, die Ihnen eine einheitliche Möglichkeit bieten, die Struktur oder die inneren Abläufe Ihres Programms von seiner öffentlich zugänglichen Schnittstelle abzugrenzen. Dies führt zu mehr Flexibilität und wiederverwendbarem Code sowie mehr Kontrolle darüber, wie Sie andere Klassen erstellen und mit ihnen interagieren. 

Genauer gesagt, sie sind ein spezielles Konstrukt in Java mit dem zusätzlichen Merkmal, mit dem Sie eine Art Mehrfachvererbung durchführen können, d. H. Klassen, die auf mehr als eine Klasse aktualisiert werden können.

Nehmen wir ein einfaches Beispiel.

  1. Angenommen, es gibt zwei Superklassen der Klassen A und B mit gleichen Methodennamen, jedoch unterschiedlichen Funktionalitäten. Durch folgenden Code mit (Erweitert) Schlüsselwort ist eine Mehrfachvererbung nicht möglich.

       public class A                               
         {
           void display()
             {
               System.out.println("Hello 'A' ");
             }
         }
    
       public class B                               
          {
            void display()
              {
                System.out.println("Hello 'B' ");
              }
          }
    
      public class C extends A, B    // which is not possible in Java
        {
          public static void main(String args[])
            {
              C object = new C();
              object.display();  // Here there is confusion,which display() to call, method from A class or B class
            }
        }
    
  2. Aber durch Schnittstellen mit Schlüsselwörtern (implementiert) ist eine Mehrfachvererbung möglich.

    interface A
        {
           // display()
        }
    
    
     interface B
        {
          //display()
        }
    
     class C implements A,B
        {
           //main()
           C object = new C();
           (A)object.display();     // call A's display
    
           (B)object.display(); //call B's display
        }
    }
    
1

Kann mir jemand genau sagen, warum es nicht erlaubt ist?

Antwort finden Sie in dieser Dokumentation Link

Ein Grund, warum die Java-Programmiersprache es nicht zulässt, mehr als eine Klasse zu erweitern, besteht darin, die Probleme der mehrfachen Vererbung von Status zu vermeiden, dh die Möglichkeit, Felder von mehreren Klassen zu erben

Wenn Mehrfachvererbung zulässig ist und Sie ein Objekt durch Instantiieren dieser Klasse erstellen, erbt dieses Objekt Felder von allen Superklassen der Klasse. Es wird zwei Probleme verursachen.

  1. Was ist, wenn Methoden oder Konstruktoren aus verschiedenen Superklassen dasselbe Feld instanziieren?

  2. Welche Methode oder Konstruktor hat Vorrang?

Obwohl jetzt mehrere Zustandsvererbungen zulässig sind, können Sie sie trotzdem implementieren 

Mehrfachvererbung vom Typ: Fähigkeit einer Klasse, mehr als eine Schnittstelle zu implementieren.

Mehrfachvererbung der Implementierung (durch Standardmethoden in Schnittstellen): Möglichkeit, Methodendefinitionen von mehreren Klassen zu erben

Weitere Informationen finden Sie in dieser verwandten SE-Frage:

Mehrdeutigkeit Mehrdeutigkeit mit Schnittstelle

0
Ravindra babu

In C++ kann eine Klasse (direkt oder indirekt) von mehr als einer Klasse erben, die als multiple Vererbung bezeichnet wird.

C # und Java beschränken die Klassen jedoch auf Einzelvererbung, wobei jede Klasse Von einer einzelnen übergeordneten Klasse erbt.

Die Mehrfachvererbung ist eine nützliche Methode zum Erstellen von Klassen, die Aspekte zweier unterschiedlicher Hierarchien der Klasse Kombinieren. Dies ist häufig der Fall, wenn verschiedene Klassenframeworks in einer einzigen -Anwendung verwendet werden. 

Wenn zwei Frameworks ihre eigenen Basisklassen für Ausnahmen definieren, können Sie zum Beispiel Mehrfachvererbung verwenden, um Exception-Klassen zu erstellen, die mit beiden Frameworks verwendet werden können.

Das Problem bei der Mehrfachvererbung ist, dass dies zu Mehrdeutigkeiten führen kann. Das klassische Beispiel ist, wenn Eine Klasse von zwei anderen Klassen erbt, von denen jede von derselben Klasse erbt:

class A {
    protected:
    bool flag;
};
class B : public A {};
class C : public A {};
class D : public B, public C {
    public:
    void setFlag( bool nflag ){
        flag = nflag; // ambiguous
    }
};

In diesem Beispiel wird das Datenelement flag durch class A definiert. class D stammt jedoch von class B Und class C ab, die beide von A abgeleitet sind. Daher sind zwei Kopien von flag verfügbar, da zwei Instanzen von A in der Klassenhierarchie von D stehen. Welches möchten Sie einstellen? Der Compiler beschwert sich , Dass der Verweis auf flag in Dmehrdeutig ist. Ein Fix besteht darin, die Referenz explizit zu disambiguieren:

B::flag = nflag;

Ein weiterer Fix ist, B und C als virtual base classes zu deklarieren. Dies bedeutet, dass nur eine Kopie von A in der Hierarchie vorhanden sein kann, wodurch Mehrdeutigkeiten beseitigt werden.

Andere Komplexitäten bestehen bei Mehrfachvererbung, z. B. der Reihenfolge, in der die Basisklassen initialisiert werden, wenn ein abgeleitetes Objekt erstellt wird, oder die Art und Weise, wie Member versehentlich aus abgeleiteten Klassen verborgen werden. Um diese Komplexität zu vermeiden, beschränken sich einige Sprachen auf das einfachere Einzelvererbungsmodell.

Obwohl dies die Vererbung erheblich vereinfacht, schränkt es jedoch auch deren Nützlichkeit ein, da nur Klassen mit einem gemeinsamen Vorfahren Verhalten haben können. Schnittstellen mildern diese Einschränkung .__ etwas, indem sie Klassen in verschiedenen Hierarchien die Möglichkeit geben, allgemeine Schnittstellen auch __ offen zu legen, wenn sie nicht durch Freigeben von Code implementiert werden.

0
zerocool