Ich habe ungefähr 8 Jahre lang codiert, aber ich finde immer noch, dass die Vererbung zu flexibel ist und Sie manchmal völlig verwirrt mit dem Code ist, den Sie geschrieben haben. Ein einfachstes Beispiel wäre:
abstract class AClass {
protected void method1() {
if(check()) {
do1();
} else {
do2();
}
}
protected abstract void do1();
protected abstract void do2();
}
Die Absicht der Klasse ist, dass die Leute do1 () und do2 () implementieren können, so dass eine weitere Logik ausgeführt werden kann. Manchmal entscheiden sich die Leute jedoch, method1 () zu überladen, und dann werden die Dinge sofort kompliziert.
Ich finde nur im Strategiemuster, dass Code durch Vererbung gut wiederverwendet wird. In den meisten Fällen kennt der Designer der Basisklasse seine Unterklassen sehr gut, und diese Vererbung ist völlig optional.
Ich habe eine Klasse, die von 4 Klassen geerbt wurde - einen IoHandler, und es gibt Unterklassen für Server-, Client-, Edgeserver- und Ursprungsserver, und sie macht mich verrückt. Ich war immer im Code-Refactoring, ich kam immer mit Ideen heraus, von denen ich denke, dass sie funktionieren würden, und wurde dann nicht bewiesen. Es wird gesagt, dass das menschliche Gehirn nur 7 Informationen gleichzeitig speichern kann. Trage ich zu viele?
quelle
final
[wenn Sie Java verwenden]. Dies macht es effektiv nicht virtuell und es kann nicht überladen werden. Perfekt für den Einsatz unter diesen Umständen [Vorlagenmuster]Antworten:
Sobald Sie solche Muster wiederholen, scheinen sie nicht mehr so schwierig zu sein.
Außerdem müssen Sie die Basisklassen kennen, bevor Sie sie erben. Und die Vererbung ist nicht optional, solange allgemeiner Code wiederverwendet wird. Nehmen Sie ein anderes Muster wie abstraktes Factory / Composite - diese Vererbung erfüllt tatsächlich einen Zweck.
Faustregel: Verwenden Sie die Vererbung nicht nur, um eine Reihe von Klassen zusammenzuhalten. Verwenden Sie es, wo immer es Sinn macht. In dem erfundenen Beispiel muss der Benutzer der untergeordneten Klasse, die die Methode1 überlastet, einen schwerwiegenden Grund dafür haben. (OTOH, ich wollte auch einen Weg finden, um zu verhindern, dass bestimmte Funktionen alleine überlastet werden - um dies zu vermeiden). Und bevor Sie diese Kinderklasse verwenden, sollten Sie auch über diese Eigenart Bescheid wissen. Aber ein reines Strategiemuster reicht nicht aus - wenn ja, dokumentieren Sie es sehr gut.
Wenn Sie Ihr aktuelles Codebeispiel angeben, können die Leute hier es für Sie überprüfen.
quelle
Ja, es kann sehr schwierig sein ... und Sie sind in guter Gesellschaft.
Joshua Bloch in Effective Java erfasst einige der Vererbungsprobleme sehr gut und empfiehlt, die Komposition anstelle der Vererbung zu bevorzugen.
quelle
Ich denke, Ihre Frage ist zu vage und allgemein. Was Sie beschreiben, klingt nach einem komplexen Problem mit oder ohne Vererbung. IMHO ist es also ganz normal, dass Sie damit zu kämpfen haben.
Natürlich ist in einigen Fällen die Vererbung nicht das beste Werkzeug für einen Job (obligatorischer Verweis auf "Komposition gegenüber Vererbung bevorzugen" ;-). Aber wenn ich es vorsichtig benutze, finde ich es nützlich. Anhand Ihrer Beschreibung ist schwer zu entscheiden, ob die Vererbung das richtige Werkzeug für Ihren Fall ist oder nicht.
quelle
Wenn Ihre Methoden zu komplex sind, werden Unterklassen zum Weinen gebracht
Lassen Sie Ihre Methoden eine bestimmte Sache tun
quelle
Die Vererbung der Zusammensetzung verengt den Änderungsvektor.
Stellen Sie sich vor, Ihre Lösung ist implementiert und Sie verwenden AClass an 300 verschiedenen Stellen der Codebasis. Jetzt müssen 45 der Aufrufe von method1 () so geändert werden, dass anstelle von do2 () eine do3 () -Methode aufgerufen wird.
Sie könnten do3 () auf der IAnInterface implementieren (hoffentlich können alle Implementierungen der Schnittstelle eine do3 () -Methode problemlos verarbeiten) und eine BClass erstellen, die do1 () oder do3 () im method1 () -Aufruf aufruft und die 45 Verweise auf ändert sowohl die AClass als auch die injizierte Abhängigkeit.
Jetzt Image, das dieselbe Änderung für do4 (), do5 (), ... implementiert.
Oder Sie könnten Folgendes tun ...
Jetzt müssen Sie nur noch eine zweite Fabrik implementieren, die entweder Doer1 oder Doer2 zurückgibt, und die Werkseinspritzung an 45 Stellen ändern. AClass ändert sich nicht, das IAnInterface ändert sich nicht und Sie können problemlos weitere Änderungen wie do4 (), do5 () verarbeiten.
quelle
Warum nicht:
(Ich denke, dass das Finale das Äquivalent von "versiegelt" in C # ist. Bitte korrigiert mich jemand, wenn diese Syntax falsch ist.)
Abhängigkeitsinjektion / IoC bedeutet, dass Sie nur die Methoden erben können, die tatsächlich geändert werden sollen, was meines Erachtens Ihr Problem löst. Außerdem hört es sich nicht so an, als würde die Hauptklasse tatsächlich tun, was auch immer do1 und do2 sind, sondern sie delegiert die Aufrufe in ihre Unterklassen, basierend auf einer Bedingung: Sie brechen die Trennung von Bedenken!
quelle