Ich lese "The Java Tutorial" (zum 2. Mal). Ich habe gerade (wieder) den Abschnitt über Schnittstellen durchgearbeitet, verstehe aber immer noch nicht, wie Java-Schnittstellen Mehrfachvererbung simulieren. Gibt es eine klarere Erklärung als das, was in dem Buch steht?
java
interface
multiple-inheritance
Jacknad
quelle
quelle
Antworten:
Angenommen, Sie haben zwei Arten von Dingen in Ihrer Domäne: Lastwagen und Küchen
LKWs haben eine driveTo () -Methode und Küchen eine cook () -Methode.
Nehmen wir nun an, Pauli beschließt, Pizzen von der Rückseite eines Lieferwagens zu verkaufen. Er will etwas, mit dem er fahren () und kochen () kann.
In C ++ würde er dazu Mehrfachvererbung verwenden.
In Java wurde dies als zu gefährlich angesehen, sodass Sie von einer Hauptklasse erben können. Sie können jedoch Verhaltensweisen von Schnittstellen "erben", die in jeder Hinsicht abstrakte Klassen ohne Felder oder Methodenimplementierungen sind.
In Java tendieren wir daher dazu, Mehrfachvererbung mithilfe von Delegierungen zu implementieren:
Pauli unterteilt einen LKW in eine Unterklasse und fügt dem LKW eine Küche in einer Mitgliedsvariablen namens Küche hinzu. Er implementiert die Küchenschnittstelle, indem er kitchen.cook () aufruft.
class PizzaTruck extends Truck implements Kitchen { Kitchen kitchen; public void cook(Food foodItem) { kitchen.cook(foodItem); } }
Er ist ein glücklicher Mann, weil er jetzt Dinge tun kann wie;
Ok, diese dumme Geschichte sollte darauf hinweisen, dass es sich nicht um eine Simulation der Mehrfachvererbung handelt, sondern um eine echte Mehrfachvererbung mit der Maßgabe, dass Sie nur den Vertrag erben können, nur von leeren abstrakten Basisklassen, die als Schnittstellen bezeichnet werden.
(Update: Mit dem Erscheinen der Standardmethoden können Schnittstellen jetzt auch ein Verhalten bereitstellen, das vererbt werden soll.)
quelle
public void cook()
), die Kitchen und PizzaTruck beide implementieren würden.default
Methoden nicht mehr korrekt . Schnittstellen noch nicht Instanz Zustand haben, aber sie tun Methoden haben eine Klasse erben können.Sie sind wahrscheinlich verwirrt, weil Sie die Mehrfachvererbung lokal in Bezug auf eine Klasse anzeigen, die Implementierungsdetails von mehreren Eltern erbt. Dies ist in Java nicht möglich (und führt häufig zu Missbrauch in Sprachen, in denen dies möglich ist).
Schnittstellen ermöglichen die mehrfache Vererbung von Typen , z. B.
class Waterfowl extends Bird implements Swimmer
kann a von anderen Klassen verwendet werden, als ob es a wäreBird
und als ob es a wäreSwimmer
. Dies ist die tiefere Bedeutung der Mehrfachvererbung: Ein Objekt kann so handeln, als ob es zu mehreren nicht verwandten verschiedenen Klassen gleichzeitig gehört.quelle
Hier ist eine Möglichkeit, eine Mehrfachvererbung über Schnittstellen in Java zu erreichen.
Was ist zu erreichen?
Klasse A erweitert B, C // Dies ist in Java nicht direkt möglich, kann aber indirekt erreicht werden.
class B{ public void getValueB(){} } class C{ public void getValueC(){} } interface cInterface{ public getValueC(); } class cChild extends C implemets cInterface{ public getValueC(){ // implementation goes here, call the super class's getValueC(); } } // Below code is **like** class A extends B, C class A extends B implements cInterface{ cInterface child = new cChild(); child.getValueC(); }
quelle
angesichts der beiden folgenden Schnittstellen ...
interface I1 { abstract void test(int i); } interface I2 { abstract void test(String s); }
Wir können beide mit dem folgenden Code implementieren ...
public class MultInterfaces implements I1, I2 { public void test(int i) { System.out.println("In MultInterfaces.I1.test"); } public void test(String s) { System.out.println("In MultInterfaces.I2.test"); } public static void main(String[] a) { MultInterfaces t = new MultInterfaces(); t.test(42); t.test("Hello"); } }
Wir können zwei Objekte NICHT erweitern, aber wir können zwei Schnittstellen implementieren.
quelle
Schnittstellen simulieren keine Mehrfachvererbung. Java-Ersteller betrachteten die Mehrfachvererbung als falsch, daher gibt es in Java keine solche.
Wenn Sie die Funktionalität von zwei Klassen zu einer kombinieren möchten, verwenden Sie die Objektzusammensetzung. Dh
public class Main { private Component1 component1 = new Component1(); private Component2 component2 = new Component2(); }
Wenn Sie bestimmte Methoden verfügbar machen möchten, definieren Sie sie und lassen Sie sie den Aufruf an den entsprechenden Controller delegieren.
Hier können Schnittstellen nützlich sein - wenn Sie
Component1
SchnittstelleInterface1
undComponent2
Geräte implementierenInterface2
, können Sie diese definierenclass Main implements Interface1, Interface2
Damit Sie Objekte austauschbar verwenden können, wo es der Kontext zulässt.
quelle
Es ist ziemlich einfach. Sie können mehr als eine Schnittstelle in einem Typ implementieren. So könnten Sie beispielsweise eine Implementierung haben
List
, die auch eine Instanz von istDeque
(und Java tut ...LinkedList
).Sie können Implementierungen einfach nicht von mehreren übergeordneten Elementen erben (dh mehrere Klassen erweitern). Deklarationen (Methodensignaturen) sind kein Problem.
quelle
Weißt du was? Aus der Perspektive eines JavaScript-Entwicklers, der versucht zu verstehen, was zum Teufel mit diesem Zeug los ist, möchte ich auf ein paar Dinge hinweisen, und jemand sagt mir bitte, was ich hier vermisse, wenn ich es bin weit weg von der Marke.
Schnittstellen sind wirklich einfach. Dumm, wahnsinnig einfach. Sie sind so dumm, wahnsinnig einfach, wie die Leute anfangs denken, weshalb es zu diesem Thema so viele doppelte Fragen gibt, weil der einzige Grund, sie zu verwenden, von Leuten unklar gemacht wurde, die versuchen, mehr aus ihnen zu machen, als sie sind und dort ist ein weit verbreiteter Missbrauch in jeder serverseitigen Java-Codebasis, der ich jemals ausgesetzt war.
Warum sollten Sie sie verwenden? Meistens würdest du nicht. Sie würden sie sicherlich nicht die ganze Zeit benutzen wollen, wie viele zu denken scheinen. Aber bevor ich zu dem Zeitpunkt komme, an dem Sie möchten, lassen Sie uns darüber sprechen, was sie NICHT sind.
Schnittstellen sind NICHT:
Sie sind wirklich so einfach, wie Sie denken, dass sie auf den ersten Blick sind. Die Leute missbrauchen die ganze Zeit dumm, daher ist es schwer zu verstehen, worum es geht. Es ist nur Validierung / Test. Sobald Sie etwas geschrieben haben, das einer Benutzeroberfläche entspricht und funktioniert, wird das Entfernen dieses "Implementierungs" -Codes nichts mehr beschädigen.
Wenn Sie die Schnittstellen jedoch korrekt verwenden, möchten Sie sie nicht entfernen, da der nächste Entwickler über ein Tool verfügt, mit dem er eine Zugriffsebene für einen anderen Satz von Datenbanken oder Webdiensten schreiben kann, damit der Rest Ihrer App fortgesetzt werden kann Verwenden, weil sie wissen, dass ihre Klasse fehlschlägt, bis sie die 100% vollständig erwartete Schnittstelle eingerichtet haben. Alles, was Schnittstellen tun, ist, Ihre Klasse zu validieren und festzustellen, dass Sie tatsächlich eine Schnittstelle implementiert haben, wie Sie es versprochen haben. Nichts mehr.
Sie sind auch tragbar. Indem Sie Ihre Schnittstellendefinitionen verfügbar machen, können Sie Personen, die Ihren unbelichteten Code verwenden möchten, eine Reihe von Methoden zur Anpassung geben, damit ihre Objekte ihn korrekt verwenden können. Sie müssen die Schnittstellen nicht implementieren. Sie konnten sie einfach auf ein Stück Notizblockpapier schreiben und das noch einmal überprüfen. Aber mit der Schnittstelle haben Sie eher eine Garantie, dass nichts versuchen wird zu funktionieren, bis es eine richtige Version der fraglichen Schnittstelle hat.
Also, wird eine Schnittstelle wahrscheinlich nie mehr als einmal implementiert? Völlig nutzlos. Mehrfachvererbung? Hör auf nach dem Regenbogen zu greifen. Java vermeidet sie aus einem bestimmten Grund und zusammengesetzte / aggregierte Objekte sind ohnehin in vielerlei Hinsicht flexibler. Das heißt nicht, dass Schnittstellen Ihnen nicht dabei helfen können, auf eine Weise zu modellieren, die Mehrfachvererbung zulässt, aber es ist wirklich keine Vererbung in irgendeiner Form und sollte nicht als solche angesehen werden. Es wird nur garantiert, dass Ihr Code erst funktioniert, wenn Sie alle von Ihnen festgelegten Methoden implementiert haben.
quelle
Y
akzeptieren kannX
. Welchen Nutzen hätte eine solche Beziehung, wenn eine solche Substitution nicht möglich wäre?Es ist keine Simulation der Mehrfachvererbung. In Java können Sie nicht von zwei Klassen erben, aber wenn Sie zwei Schnittstellen implementieren, "scheint es, als hätten Sie von zwei verschiedenen Klassen geerbt", weil Sie Ihre Klasse als eine Ihrer beiden Schnittstellen verwenden können.
Zum Beispiel
interface MyFirstInteface{ void method1(); } interface MySecondInteface{ void method2(); } class MyClass implements MyFirstInteface, MySecondInteface{ public void method1(){ //Method 1 } public void method2(){ //Method 2 } public static void main(String... args){ MyFirstInterface mfi = new MyClass(); MySecondInterface msi = new MyClass(); } }
Dies wird funktionieren und Sie können mfi und msi verwenden. Es scheint eine Mehrfachvererbung zu sein, aber nicht, weil Sie nichts erben, sondern nur die von den Schnittstellen bereitgestellten öffentlichen Methoden neu schreiben.
quelle
Sie müssen genau sein:
Java erlaubt die mehrfache Vererbung der Schnittstelle, jedoch nur die einmalige Vererbung der Implementierung.
Sie vererben die Schnittstelle in Java mehrfach wie folgt:
public interface Foo { String getX(); } public interface Bar { String getY(); } public class MultipleInterfaces implements Foo, Bar { private Foo foo; private Bar bar; public MultipleInterfaces(Foo foo, Bar bar) { this.foo = foo; this.bar = bar; } public String getX() { return this.foo.getX(); } public String getY() { return this.bar.getY(); } }
quelle
Übrigens ist der Grund, warum Java keine vollständige Mehrfachvererbung implementiert, der, dass es Mehrdeutigkeiten erzeugt. Angenommen, Sie könnten sagen "A erweitert B, C", und dann haben sowohl B als auch C die Funktion "void f (int)". Welche Implementierung erbt A? Mit dem Java-Ansatz können Sie eine beliebige Anzahl von Schnittstellen implementieren, aber Schnittstellen deklarieren nur eine Signatur. Wenn also zwei Schnittstellen Funktionen mit derselben Signatur enthalten, muss Ihre Klasse eine Funktion mit dieser Signatur implementieren. Wenn von Ihnen geerbte Schnittstellen Funktionen mit unterschiedlichen Signaturen haben, haben die Funktionen nichts miteinander zu tun, sodass von einem Konflikt keine Rede ist.
Ich sage nicht, dass dies der einzige Weg ist. C ++ implementiert eine echte Mehrfachvererbung, indem Prioritätsregeln festgelegt werden, deren Implementierung gewinnt. Die Autoren von Java beschlossen jedoch, die Mehrdeutigkeit zu beseitigen. Ob aus philosophischer Überzeugung, dass dies zu saubererem Code führte, oder weil sie nicht die ganze zusätzliche Arbeit machen wollten, weiß ich nicht.
quelle
Es ist nicht fair zu sagen, dass Schnittstellen Mehrfachvererbung "simulieren".
Sicher, Ihr Typ kann mehrere Schnittstellen implementieren und so viele verschiedene Typen polymorph agieren. Sie werden jedoch offensichtlich kein Verhalten oder keine Implementierungen unter dieser Anordnung erben.
Schauen Sie sich im Allgemeinen die Komposition an, bei der Sie der Meinung sind, dass Sie möglicherweise mehrere Vererbungen benötigen.
ODER Eine mögliche Lösung, um eine Mehrfachvererbung zu erreichen, ist die Mixin-Oberfläche - http://csis.pace.edu/~bergin/patterns/multipleinheritance.html . Vorsichtig verwenden!
quelle
Sie tun es nicht.
Ich denke, dass die Verwirrung von Leuten kommt, die glauben, dass die Implementierung einer Schnittstelle eine Form der Vererbung darstellt. Es tut nicht; Die Implementierung kann einfach leer sein, kein Verhalten wird durch die Handlung erzwungen oder durch einen Vertrag garantiert. Ein typisches Beispiel ist die Clonable-Schnittstelle, die zwar auf viele großartige Funktionen anspielt, aber so wenig definiert, dass sie im Wesentlichen nutzlos und potenziell gefährlich ist.
Was erben Sie durch die Implementierung einer Schnittstelle? Bubkes! Hören Sie meiner Meinung nach auf, die Wörter Schnittstelle und Vererbung im selben Satz zu verwenden. Wie Michael Borgwardt sagte, ist eine Schnittstelle keine Definition, sondern ein Aspekt.
quelle
Sie können tatsächlich von mehreren konkreten Klassen "erben", wenn diese selbst Schnittstellen implementieren.
innerclasses
helfen Ihnen dabei:interface IBird { public void layEgg(); } interface IMammal { public void giveMilk(); } class Bird implements IBird{ public void layEgg() { System.out.println("Laying eggs..."); } } class Mammal implements IMammal { public void giveMilk() { System.out.println("Giving milk..."); } } class Platypus implements IMammal, IBird { private class LayingEggAnimal extends Bird {} private class GivingMilkAnimal extends Mammal {} private LayingEggAnimal layingEggAnimal = new LayingEggAnimal(); private GivingMilkAnimal givingMilkAnimal = new GivingMilkAnimal(); @Override public void layEgg() { layingEggAnimal.layEgg(); } @Override public void giveMilk() { givingMilkAnimal.giveMilk(); } }
quelle
Ich möchte auf etwas hinweisen, das mich in den Hintergrund gedrängt hat und aus C ++ stammt, wo Sie auch viele Implementierungen leicht erben können.
Eine "breite" Schnittstelle mit vielen Methoden bedeutet, dass Sie viele Methoden in Ihren konkreten Klassen implementieren müssen und diese nicht einfach für Implementierungen freigeben können.
Zum Beispiel:
interface Herbivore { void munch(Vegetable v); }; interface Carnivore { void devour(Prey p); } interface AllEater : public Herbivore, Carnivore { }; class Fox implements AllEater { ... }; class Bear implements AllEater { ... };
In diesem Beispiel können Fox und Bear keine gemeinsame Basisimplementierung für die Schnittstellenmethoden
munch
und gemeinsam nutzendevour
.Wenn die Basisimplementierungen so aussehen, möchten wir sie möglicherweise für
Fox
und verwendenBear
:class ForestHerbivore implements Herbivore void munch(Vegetable v) { ... } }; class ForestCarnivore implements Carnivore void devour(Prey p) { ... } };
Aber wir können nicht beide erben. Die Basisimplementierungen müssen Mitgliedsvariablen in der Klasse sein, und die definierten Methoden können diese weiterleiten. Dh:
class Fox implements AllEater { private ForestHerbivore m_herbivore; private ForestCarnivore m_carnivore; void munch(Vegetable v) { m_herbivore.munch(v); } void devour(Prey p) { m_carnivore.devour(p); } }
Dies wird unhandlich, wenn Schnittstellen wachsen (dh mehr als 5-10 Methoden ...)
Ein besserer Ansatz besteht darin, eine Schnittstelle als eine Aggregation von Schnittstellen zu definieren:
interface AllEater { Herbivore asHerbivore(); Carnivore asCarnivore(); }
Dies bedeutet, dass
Fox
und müssenBear
nur diese beiden Methoden implementiert werden, und die Schnittstellen und Basisklassen können unabhängig von der aggregiertenAllEater
Schnittstelle wachsen , die die implementierenden Klassen betrifft.Weniger Kopplung auf diese Weise, wenn es für Ihre App funktioniert.
quelle
Ich glaube nicht.
Vererbung ist speziell eine implementierungsorientierte Beziehung zwischen Implementierungen. Schnittstellen liefern überhaupt keine Implementierungsinformationen, sondern definieren einen Typ. Um eine Vererbung zu haben, müssen Sie einige Verhaltensweisen oder Attribute speziell von einer übergeordneten Klasse erben.
Ich glaube, hier gibt es irgendwo eine Frage speziell zur Rolle von Schnittstellen und Mehrfachvererbung, aber ich kann sie jetzt nicht finden ...
quelle
Es gibt wirklich keine Simulation der Mehrfachvererbung in Java.
Manchmal wird gesagt, dass Sie mithilfe von Schnittstellen mehrere Vererbungen simulieren können, da Sie mehr als eine Schnittstelle pro Klasse implementieren und dann die Komposition (anstelle der Vererbung) in Ihrer Klasse verwenden können, um das Verhalten der mehreren Klassen zu erreichen, von denen Sie erben wollten zunächst.
quelle
Wenn es in Ihrem Objektmodell sinnvoll ist, können Sie natürlich von einer Klasse erben und auch eine oder mehrere Schnittstellen implementieren.
quelle
Es gibt Fälle, in denen Mehrfachvererbung sehr praktisch und schwer durch Schnittstellen zu ersetzen ist, ohne mehr Code zu schreiben. Beispielsweise gibt es Android-Apps, die Klassen verwenden, die von Activity und andere von FragmentActivity in derselben App abgeleitet sind. Wenn Sie eine bestimmte Funktion haben, die Sie in einer gemeinsamen Klasse freigeben möchten, müssen Sie in Java Code duplizieren, anstatt untergeordnete Klassen von Activity und FragmentsActivity von derselben SharedFeature-Klasse ableiten zu lassen. Und die schlechte Implementierung von Generika in Java hilft auch nicht, da das Schreiben von Folgendem illegal ist:
public class SharedFeature<T> extends <T extends Activity> ... ...
quelle
Mehrfachvererbung in Java wird nicht unterstützt.
Diese Geschichte der Unterstützung der Mehrfachvererbung über die Benutzeroberfläche haben wir Entwickler erfunden. Die Schnittstelle bietet Flexibilität als konkrete Klassen und wir haben die Möglichkeit, mehrere Schnittstellen mit einer einzigen Klasse zu implementieren. Dies ist nach Vereinbarung, wir halten uns an zwei Blaupausen, um eine Klasse zu erstellen.
Dies versucht, der Mehrfachvererbung näher zu kommen. Wir implementieren mehrere Schnittstellen, hier erweitern (erben) wir nichts. Die implementierende Klasse ist diejenige, die die Eigenschaften und das Verhalten hinzufügt. Die Implementierung wird nicht frei von den übergeordneten Klassen. Ich würde einfach sagen, es gibt keine Unterstützung für Mehrfachvererbung in Java.
quelle
Nein, Java unterstützt keine Mehrfachvererbung. Weder mit Klasse noch mit Schnittstelle. Weitere Informationen finden Sie unter diesem Link unter https://devsuyed.wordpress.com/2016/07/21/does-java-support-multiple-inheritance
quelle
Ich muss auch sagen, dass Java keine Mehrfachvererbung unterstützt.
Sie müssen die Bedeutung zwischen
extends
undimplements
Schlüsselwörtern in Java unterscheiden. Wenn wir verwendenextends
, erben wir die Klasse tatsächlich nach diesem Schlüsselwort. Um alles zu vereinfachen, können wir jedoch nichtextends
mehr als einmal verwenden. Sie können jedoch beliebig viele Schnittstellen implementieren.Wenn Sie eine Schnittstelle implementieren, besteht keine Wahrscheinlichkeit, dass Sie die Implementierung aller Methoden in jeder Schnittstelle verpassen (Ausnahme: Standardimplementierungen von in Java 8 eingeführten Schnittstellenmethoden). Sie wissen also jetzt genau, was mit den Dingen passiert dass Sie in Ihre neue Klasse eingebettet haben.
Warum Java keine Mehrfachvererbung zulässt, ist, dass Mehrfachvererbung den Code etwas komplexer macht. Manchmal können zwei Methoden übergeordneter Klassen aufgrund derselben Signaturen in Konflikt geraten. Wenn Sie jedoch gezwungen sind, alle Methoden manuell zu implementieren, erhalten Sie, wie oben erwähnt, das vollständige Verständnis darüber, was vor sich geht. Es macht Ihren Code für Sie verständlicher.
Wenn Sie weitere Informationen zu Java-Schnittstellen benötigen, lesen Sie diesen Artikel unter http://www.geek-programmer.com/introduction-to-java-interfaces/.
quelle
interface ParentOne{ public String parentOneFunction(); } interface ParentTwo{ public String parentTwoFunction(); } class Child implements ParentOne,ParentTwo{ @Override public String parentOneFunction() { return "Parent One Finction"; } @Override public String parentTwoFunction() { return "Parent Two Function"; } public String childFunction(){ return "Child Function"; } } public class MultipleInheritanceClass { public static void main(String[] args) { Child ch = new Child(); System.out.println(ch.parentOneFunction()); System.out.println(ch.parentTwoFunction()); System.out.println(ch.childFunction()); } }
quelle