Frage

In Java ist es je ein Fall dafür, dass eine nicht-abstrakte Klasse erweitert werden?

Es scheint immer schlechter Code, um anzuzeigen, wenn Klassenhierarchien sind. Stimmen Sie zu, und warum / warum nicht?

War es hilfreich?

Lösung

Ich stimme mit Jon und Kent aber, wie Scott Myers (in Effective C ++), ich gehe viel weiter. Ich glaube, dass Jede Klasse sollte entweder abstract sein, oder final . Das heißt, nur Blatt Klassen in einer Hierarchie sind wirklich geeignet für die direkte Instanziierung. Alle anderen Klassen (das heißt innere Knoten in der Vererbung) sind „unfertig“ und folglich abstract werden sollte.

Es macht einfach keinen Sinn für üblichen Klassen weiter ausgebaut werden. Wenn ein Aspekt der Klasse lohnt mich erstreckt und / oder zu modifizieren, die sauberere Möglichkeit, dass eine Klasse zu nehmen wäre und es in eine abstract Basisklasse zu trennen und eine konkrete austauschbare Umsetzung.

Andere Tipps

Es gibt sicherlich Zeiten, in denen es sinnvoll ist, nicht endgültige konkrete Klassen zu haben. Allerdings bin ich mit Kent - Ich glaube, dass Klassen endgültig sein sollten (in C # versiegelt) standardmäßig, und die Java-Methoden sollten standardmäßig endgültig sein (wie sie in C # sind)

.

Wie Kent sagt, erfordert Erbe sorgfältige Gestaltung und Dokumentation - es ist sehr einfach, Sie zu denken, können nur eine einzige Methode außer Kraft setzen, aber weiß nicht, die Situationen, in denen das Verfahren kann von der Basisklasse als Teil des Restes der heißen Umsetzung.

Siehe „Wie gestalten Sie eine Klasse für die Vererbung“ für weitere Diskussion zu diesem Thema.

Diese Frage ist ebenso auf andere Plattformen wie C # .NET. Es gibt diejenigen, (mich eingeschlossen), die Typen glauben sollte standardmäßig final / versiegelt sein und müssen explizit erlauben Vererbung entsiegelt werden.

Erweiterung durch Vererbung ist etwas, das sorgfältige Design braucht und ist nicht so einfach wie nur eine Art entsiegelt verlassen. Daher denke ich, es sollte eine explizite Entscheidung sein Erbe zu ermöglichen.

gibt es einen guten Gründe Ihren Code nicht endgültig zu halten. viele Frameworks wie Hibernate, Spring, guice hängen manchmal auf nicht-final-Klassen, die sie zur Laufzeit dynamisch erweitert.

zum Beispiel Hibernate verwendet Proxies für lazy fetching Vereinigung. vor allem, wenn es um AOP kommt, werden Sie Ihre Klassen nicht-Finale wollen, so dass die Abfangjäger daran anschließen können. siehe auch die Frage auf SO

Ihre beste Referenz ist hier Artikel 15 von Joshua Bloch ausgezeichneten Buch „Effective Java“, die so genannten „Entwurf und Dokument für die Vererbung oder aber es verbieten“. Doch der Schlüssel, ob Erweiterung einer Klasse soll erlaubt werden, ist nicht „ist es abstrakt“, aber „war es mit Vererbung entworfen im Auge“. Es ist manchmal eine Korrelation zwischen den beiden, aber es ist die zweite, die wichtig ist. So nehmen Sie ein einfaches Beispiel die meisten der AWT Klassen ausgelegt sind, erweitert werden, auch solche, die nicht abstrakt sind.

Die Zusammenfassung des Kapitels Blochs ist, dass die Interaktion von geerbten Klassen mit ihren Eltern überraschend sein kann und unvorhersehbare, wenn die Vorfahren nicht geerbt werden entworfen wurde. Klassen sollten daher in zwei Arten kommen a) Klassen entworfen erweitert werden, und mit genug Dokumentation zu beschreiben, wie es b) Klassen markierten endgültig getan werden soll. Klassen in (a) werden oft abstrakt sein, aber nicht immer. Für

In einigen Fällen können Sie sicherstellen möchten, gibt es keine Unterklassen, in anderen Fällen wollen Sie Subklassifizieren (Zusammenfassung) zu gewährleisten. Aber es gibt immer eine große Teilmenge von Klassen, in denen Sie als den ursprünglichen Autor kümmern sich nicht und sollte nicht kümmern. Es ist ein Teil offen / geschlossen. Die Entscheidung, das ist etwas, geschlossen werden sollte auch aus einem bestimmten Grund geschehen.

ich nicht zustimmen. Wenn Hierarchien schlecht wäre, würde es keinen Grund für objektorientierte Sprachen zu existieren. Wenn Sie bei UI-Widget-Bibliotheken von Microsoft und Sun suchen, sind Sie sicher, Erbe zu finden. Ist das alles „schlechte Code“ per Definition? Nein, natürlich nicht.

Die Vererbung kann missbraucht werden, aber so kann jede Sprache-Funktion. Der Trick ist, zu lernen, wie die Dinge in geeigneter Weise zu tun.

Ich kann nicht mehr widersprechen. Klassenhierarchien machen für konkrete Klassen sinnvoll, wenn die konkreten Klassen der mögliche Rückgabe Arten von Methoden wissen, dass sie nicht endgültig markiert. Zum Beispiel kann eine konkrete Klasse eine Unterklasse Haken hat:

protected SomeType doSomething() {
return null;
}

Dieses doSomething ist guarenteed entweder null oder eine Instanz Sometype zu sein. Sagen Sie, dass Sie die Fähigkeit haben, die Instanz zu verarbeiten Sometype aber für die Verwendung der Instanz Sometype in der aktuellen Klasse keinen Anwendungsfall haben, wissen aber, dass diese Funktionalität wirklich gut wäre, in Subklassen zu haben und fast alles ist Beton. Es macht keinen Sinn, die aktuelle Klasse eine abstrakte Klasse zu machen, wenn sie direkt mit dem Standard verwendet werden können, hat nichts mit seinem Null-Wert zu tun. Wenn Sie es eine abstrakte Klasse gemacht, dann würden Sie ihre Kinder in dieser Art von Hierarchie haben:

  • Abstrakte Basisklasse
    • Standardklasse (die Klasse, die nicht abstrakt gewesen wäre, implementiert nur die geschützte Methode und nichts anderes)
    • Andere Unterklassen.

Sie also eine abstrakte Basisklasse, die nicht direkt verwendet werden kann, wenn die Standardklasse der häufigste Fall sein kann. In der anderen Hierarchie gibt es eine weniger Klasse, so dass die Funktionalität kann, ohne dass eine im Wesentlichen nutzlos Standardklasse verwendet werden, da Abstraktion nur auf die Klasse gezwungen werden mußte.

  • Standardklasse
    • Andere Unterklassen.

Nun, sicher, können Hierarchien verwendet und missbraucht werden, und wenn die Dinge nicht klar dokumentiert oder Klassen nicht gut gestaltet, können Subklassen auf Probleme stoßen. Aber dieselben Probleme bestehen mit abstrakten Klassen auch, bekommt man nicht loswerden das Problem, nur weil Sie „abstrakt“ zu Ihrer Klasse hinzuzufügen. Zum Beispiel, wenn der Vertrag des „doSomething ()“ Methode oben erforderlich Sometype zu x bevölkert hat, y und z Felder, wenn sie über Getter und Setter zugegriffen wurden, würde die Unterklasse unabhängig sprengen, wenn Sie die konkrete Klasse verwendet, die null zurück als Basisklasse oder eine abstrakte Klasse.

Die Faustregel für eine Klassenhierarchie Gestaltung ist so ziemlich ein einfaches questionaire:

  1. Habe ich das Verhalten meiner vorgeschlagenen geordneten Klasse in meiner Unterklasse müssen? (Y / N) Dies ist die erste Frage, die Sie sich stellen müssen. Wenn Sie nicht das Verhalten benötigen, gibt es kein Argument für Subclassing.

  2. Muss ich den Zustand meiner vorgeschlagenen übergeordneten Klasse in meine Unterklasse müssen? (Y / N) Dies ist die zweite Frage. Wenn der Staat das Modell von dem, was paßt Sie benötigen, kann dies ein canidate für Subklassifizieren sein.

  3. Wenn die Unterklasse aus der vorgeschlagenen Super erstellt wurde, wäre es wirklich eine IS-A Beziehung sein, oder ist es nur eine Abkürzung Verhalten und Zustand zu erben? Dies ist die letzte Frage. Wenn es nur eine Abkürzung und Sie können Ihre vorgeschlagenen Unterklasse nicht qualifizieren „as-a“ Superklasse, dann sollte Erbe vermieden werden. Der Staat und die Logik können mit einer anderen Wurzel in die neue Klasse kopiert und eingefügt werden, oder eine Delegation verwendet werden kann.

Nur wenn eine Klasse des Verhalten, Staat braucht und kann in Betracht gezogen werden, dass die Unterklasse IST-A (n) Instanz der übergeordneten Klasse soll berücksichtigt werden, von einer übergeordneten Klasse erben. Ansonsten gibt es andere Optionen, die besser zu dem Zweck geeignet wäre, auch wenn es vorne ein wenig mehr Arbeit erfordern, ist es sauberer auf lange Sicht.

Es gibt einige Fälle, in denen wir nicht wollen, zu ermöglichen, das Verhalten zu ändern. Zum Beispiel String-Klasse, Math.

Ich mag Vererbung nicht, denn es gibt immer einen besseren Weg, die gleiche Sache zu tun, aber wenn Sie Wartung Änderungen in einem großen System machen manchmal den besten Weg, den Code mit einem minimalen Änderungen zu beheben ist, eine Klasse, ein wenig zu verlängern . Ja, es ist in der Regel führt zu einem schlechten Code, sondern zu einer Funktion eines und ohne Monate nach dem ersten neu zu schreiben. So gibt ein Haus so viel Flexibilität wie er bewältigen kann ein guter Weg zu gehen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top