2016-04-04 6 views
1

Betrachten Sie die folgenden zwei Klassen:Ist es eine schlechte Methode, Vererbung zu verwenden, wenn ich alle Methoden überschreiben möchte?

class A { 
    String _name; 
    char _type; 

    public A(String name, char type) { 
     _name = name; _type = type; 
    } 

    public int method1() { 
     do_something...; 
    } 

    public String method2() { 
     make_something...; 
    } 
} 

und

class B extends A { 
    public B(String name) { 
     super(name, 'a'); 
    } 

    @Override 
    public int method1() { 
     do_something_else...; 
    } 

    @Override 
    public String method2() { 
     String answer = super.method2(); 
     answer += more_processing...; 
    } 
} 

ich Erbschaft hier verwende, weil die Klassen viele Dinge gemeinsam haben. Jedoch, weil ich alle Methoden aus der Oberklasse überschreibe, ist es eine gute Idee, die Vererbung hier zu verwenden?

+0

Was genau sie gemeinsam haben? –

+0

die Felder, und die Unterklassenmethoden rufen die Superklassenmethoden zu Zeiten auf –

+0

In diesem Beispiel wird Vererbung nicht wirklich verwendet, weil 'B' nicht' A' erweitert. Aber wenn es so wäre, würde die Vererbung Sinn ergeben, wenn Sie wollen, dass 'B' das Verhalten von' A' erbt und Sie nur 'B' anpassen möchten und/oder Sie' B' Objekte mit 'A' herumreichen wollen Zeiger anstelle von 'B' Zeigern. –

Antwort

1

Sie müssen sich die Frage stellen: Ist Klasse B eine Unterklasse der Klasse A?

Das Überschreiben der Methoden spielt keine Rolle, solange Sie verstehen, wofür die Vererbung verwendet wird. (d. h. Klasse B ist ein Subtyp der Klasse A, macht aber etwas anderes)

2

Das hängt vom Kontext ab. Wenn Sie viele Features der Klasse (Attribute und Methoden) verwenden möchten, müssen Sie die Vererbung verwenden und die wenigen Methoden überschreiben, die Sie ändern müssen. Wenn Sie nur wenige Funktionen verwenden und fast alle Methoden überschreiben müssen, erstellen Sie besser eine neue Klasse. Ein anderer Fall könnte sein, wenn eine bestimmte Methode der Klasse sehr schwer zu programmieren ist oder eine sehr wichtige Implementierung hat, wieder kommt es auf den Kontext an.

1

Die entscheidende Frage, die Sie stellen müssen, ist:

"Ist B ein A?"

Wenn ja, dann ist die Verwendung der Vererbung wahrscheinlich eine gute Idee.

Obwohl Sie möglicherweise keine Methoden haben, die in beiden Klassen die gleiche Implementierung haben, könnte sich das in Zukunft ändern, da Sie und andere, die an Ihrer Codebasis arbeiten, neue Methoden hinzufügen können.

Eine weitere Frage, die Sie stellen müssen, ist, ob jede Methode und ihre überschriebene Version sich unterscheiden, WAS sie tun, oder nur WIE sie sich verhalten? Wenn es das letztere ist, dann ist die Vererbung wahrscheinlich der Weg zu gehen.

Wo ich arbeite, halten wir es für die beste Praxis, Schnittstellen (Zusammensetzung) möglichst über Vererbung zu verwenden. Dies liegt zum Teil daran, dass eine Klasse mehrere Schnittstellen in Java implementieren kann, aber nur eine Klasse durch Vererbung erweitern kann. Es gibt andere Gründe, aber ich möchte nicht zu off-topic gehen. Wenn jedoch die Beziehung zwischen den Klassen, die Sie geschrieben haben, mehr ist, als dass sie nur ähnliche Mitglieder haben, anstatt eine "ist-a" -Beziehung zu haben, dann sollten Sie diese geteilten Mitglieder (Methoden und Felder) stattdessen in eine Schnittstelle einfügen Vererbung verwenden.

1

Vererbung sollte immer dann verwendet werden, wenn Sie eine Instanz des Super-Typs A durch eine Instanz des Untertyps B ersetzen können, ohne etwas zu beschädigen. Dies wird auch als Liskov substitution principle bekannt.

Eine andere Art von Hacky, aber immer noch gültigen Fall für die Vererbung ist, wenn Sie Zugriff auf sonst nicht zugreifbare Methoden oder Eigenschaften des Super-Typ A. In diesem Fall bevorzuge ich nicht direkt B den Super-Typ A zu erweitern, sondern eine innere Klasse B.ChildOfA zu verwenden, die den Super-Typ A erweitert. Dies verhindert, dass B als Instanz von A verwendet wird, wenn dies nicht angemessen ist.

Im Allgemeinen sollten Sie prefer composition over inheritance.

Um Ihre Frage zu beantworten: Es kommt nicht darauf an, ob Sie alles überschreiben, sondern wie Ihre Unterklasse verwendet werden kann oder soll.

Wenn Sie alles von A in B außer Kraft setzen und Sie delegieren nicht auf den Super-Typen A, aber beiden Typen noch austauschbar sein sollten von dem Liskov Substitutionsprinzip definiert wie, dann auch Sie eine dritte Option: Sie können Deklarieren Sie einen gemeinsamen Super-Typ I und lassen Sie beide Klassen erben. Der neu eingeführte Super-Typ I kann eine Schnittstelle oder eine Klasse sein. Dies ist natürlich nur möglich, wenn Sie die Klasse A besitzen, weil Sie sie ändern müssen, um den neuen Super-Typ I zu erben.

1

In diesem Fall, wo B alles erben eigentlich nicht von A es mehr Sinn, eine gemeinsame interface, die sowohl A und B auf ihre eigene Weise umsetzen nutzen machen kann. Kontext ist wichtig, wenn Sie diese Art von Vererbungsentscheidungen treffen.

public interface SomeInterface { 

    public int method1(); 

    public String method2(); 

} 

A:

public class A implements SomeInterface { 

B:

public class B implements SomeInterface { 
+0

'Klasse B erweitert A'. – ChiefTwoPencils

Verwandte Themen