Sollte ich eine Schnittstelle direkt implementieren oder von der Superklasse ausführen lassen?

14

Gibt es einen Unterschied zwischen

public class A extends AbstractB implements C
{...}

gegen...

public class A extends AbstractB
{...}
abstract class AbstractB implements C
{...}

Ich verstehe, dass Klasse A in beiden Fällen der Schnittstelle entspricht. Im zweiten Fall AbstractBkann die Implementierung für Schnittstellenmethoden in bereitgestellt werden C. Ist das der einzige Unterschied?

Wenn ich will nicht in eine Implementierung für jede der Schnittstellenverfahren zur Verfügung zu stellen AbstractB , welche Art sollte ich verwenden ? Hat die Verwendung des einen oder anderen Dokuments einen versteckten Zweck?

c_maker
quelle
3
vorschlag zum titel: sollte ich eine schnittstelle direkt implementieren oder von der überklasse ausführen lassen
jeanne

Antworten:

20

Es hängt alles davon ab, ob AbstractB implements Csemantisch. Dh wenn es semantisch sinnvoll ist, es AbstractBzu implementieren C, dann machen Sie es.

An konkreten Beispielen wird der semantische Unterschied deutlich.

Wenn A = Hund, AbstractB = Tier, C = IBark

Die einzig sinnvolle Wahl ist

class Dog extends Animal implements IBark{

Dies macht keinen Sinn, da dies bedeuten würde, dass alle Tiere bellen.

class Animal implements IBark{

Die anderen Unterschiede kommen ins Spiel, wenn Sie mehr als nur class Aerben AbstractB. In # 1 müssen sie C nicht implementieren, in # 2 sind sie alle gezwungen, C zu implementieren.

Karthik T
quelle
1
+1 Weit deutlicher als meine Antwort!
Hand-E-Food
Wenn die Schnittstelle vorhanden wäre, wäre Heterotrophes außerdem sinnvoll, sie Animalimplementieren zu lassen Heterotroph. Wenn Sie viele andere bellende Tiere erwarten und sie auf die gleiche Weise behandeln möchten, ist eine andere Klasse BarkingAnimal extends Animal implements IBarkder richtige Weg.
scarfridge
@ scarfridge Eigentlich würde ich erwarten, dass Tier zu verlängern, Heterotrophaber danke für Ihre Eingabe
Karthik T
2

Der einfache Weg, die richtige Vererbungsbeziehung zu bestimmen, besteht nicht darin, die Klassen selbst zu betrachten, sondern den Code, der Methoden für diese Klassen aufruft . Irgendwo in Ihrem Code haben Sie etwas wie AbstractB b = new A();oder otherObject.addAbstractB(this);. In beiden Fällen verwenden Sie diese AbstractBReferenz später, um verschiedene Methodenaufrufe durchzuführen.

Wollen Sie in dieser Situation Methoden von aufrufen C? Wenn ja, dann AbstractBsollte implementieren C. Wenn nicht, sollte es nicht. Wenn Sie keine derartigen Situationen haben, benötigen Sie keine Vererbung und sollten die Komposition neu definieren, da sie viel lockerer gekoppelt ist.

Karl Bielefeldt
quelle
2

Es ist kein "versteckter" Dokumentationszweck. Sie können AbstractB und alle seine Unterklassen in C umwandeln. Es gibt tatsächlich drei Stile.

public class A extends AbstractB implements C
public class AbstractB

Ich würde dieses verwenden, wenn AbstractB C nicht logisch implementieren würde. Auch wenn es die Methoden nicht bereitstellt, könnte es eine Bedeutung haben. Wie Dog erweitert Animal Wag Utensilien. Es macht nicht für alle Tiere Sinn, Wag. Beachten Sie, dass dieser Ansatz AbstractB nicht davon abhält, die Implementierung bereitzustellen.

public class A extends AbstractB
public AbstractB implements C

Ich würde diese verwenden, wenn alle Unterklassen die Schnittstelle implementieren sollen UND es für alle von ihnen sinnvoll ist, dies zu tun. Wie Beagle erweitert AbstractDog Wag.

public class A extends AbstractB implements C
public class AbstractB implements C

Dieser ist überflüssig, kann aber zu mehr Klarheit führen.

Jeanne Boyarsky
quelle
Ich denke, "AbstractC" (was in der Frage nicht vorhanden ist) im 2. Absatz sollte in "AbstractB" geändert werden. Ich kann das nicht bearbeiten, da die Edisten mindestens 6 Zeichen haben müssen.
cellepo