it-swarm.com.de

Gute Gründe, die Vererbung in Java zu verbieten?

Was sind gute Gründe, um die Vererbung in Java zu verbieten, z. B. durch die Verwendung von final-Klassen oder Klassen mit einem einzigen privaten Konstruktor ohne Parameter? Was sind gute Gründe, eine Methode endgültig zu machen?

155
cretzel

Ihre beste Referenz ist hier Punkt 19 von Joshua Blochs ausgezeichnetem Buch "Effective Java" mit dem Titel "Design und Dokument zur Vererbung oder zum Verbot". (Es ist Punkt 17 in der zweiten Ausgabe und Punkt 15 in der ersten Ausgabe.) Sie sollten es wirklich lesen, aber ich werde zusammenfassen.

Die Interaktion von geerbten Klassen mit ihren Eltern kann überraschend und unvorhersehbar sein, wenn der Vorfahr nicht dafür ausgelegt ist, von ihnen geerbt zu werden.

Klassen sollten daher in zwei Arten kommen:

  1. Klassen wurden entwickelt, um erweitert zu sein, und mit genügend Dokumentation, um zu beschreiben, wie es gemacht werden sollte

  2. Klassen markiert endgültig

Wenn Sie rein internen Code schreiben, kann dies ein wenig übertrieben sein. Der zusätzliche Aufwand für das Hinzufügen von fünf Zeichen zu einer Klassendatei ist jedoch sehr gering. Wenn Sie nur für den internen Verbrauch schreiben, kann ein zukünftiger Codierer immer das 'endgültige' entfernen - Sie können es als Warnung betrachten, die besagt, dass diese Klasse nicht für die Vererbung konzipiert wurde.

170
DJClayworth

Möglicherweise möchten Sie eine Methode finalisieren, damit überschreibende Klassen das Verhalten, auf das in anderen Methoden gesetzt wird, nicht ändern können. In Konstruktoren aufgerufene Methoden werden oft als final deklariert, damit Sie beim Erstellen von Objekten keine unangenehmen Überraschungen erleben.

22
Bill the Lizard

Ein Grund, eine Klasse endgültig zu machen, wäre, wenn Sie die Komposition über die Vererbung erzwingen möchten. Dies ist im Allgemeinen wünschenswert, um eine enge Kopplung zwischen Klassen zu vermeiden.

17
John Topley

Es gibt 3 Anwendungsfälle, in denen Sie sich für endgültige Methoden entscheiden können.

  1. Um zu vermeiden, dass abgeleitete Klassen eine bestimmte Basisklassenfunktionalität überschreiben.
  2. Dies dient Sicherheitszwecken, bei denen die Basisklasse einige wichtige Kernfunktionen des Frameworks bereitstellt, bei denen die abgeleitete Klasse dies nicht ändern soll.
  3. Endgültige Methoden sind schneller als Instanzmethoden, da das Konzept der virtuellen Tabelle für endgültige und private Methoden nicht verwendet wird. Versuchen Sie also, wo immer die Möglichkeit besteht, die endgültigen Methoden anzuwenden.

Zweck für eine endgültige Klasse:

Damit niemand diese Klassen erweitern und ihr Verhalten ändern kann.

Beispiel: Wrapper-Klasse Integer ist eine letzte Klasse. Wenn diese Klasse nicht endgültig ist, kann jeder Integer in seine eigene Klasse erweitern und das grundlegende Verhalten der Integer-Klasse ändern. Um dies zu vermeiden, haben Java alle Wrapper-Klassen als endgültige Klassen definiert.

13
user1923551

möglicherweise möchten Sie unveränderliche Objekte erstellen ( http://en.wikipedia.org/wiki/Immutable_object ). Möglicherweise möchten Sie einen Singleton erstellen ( http: //en.wikipedia). org/wiki/Singleton_pattern ), oder Sie möchten möglicherweise verhindern, dass jemand die Methode aus Gründen der Effizienz, Sicherheit oder des Schutzes überschreibt.

12
Ray Tayek

Vererbung ist wie eine Kettensäge - sehr mächtig, aber schrecklich in den falschen Händen. Entweder entwerfen Sie eine Klasse, von der geerbt werden soll (was die Flexibilität einschränken und viel länger dauern kann), oder Sie sollten sie verbieten.

Siehe Effective Java Punkt 16 und 17 der 2. Ausgabe, oder meinen Blog-Beitrag "Inheritance Tax" .

6
Jon Skeet

Hmmm ... mir fallen zwei Dinge ein:

Möglicherweise haben Sie eine Klasse, die sich mit bestimmten Sicherheitsproblemen befasst. Ein Angreifer kann Sicherheitsbeschränkungen umgehen, indem er sie unterordnet und Ihrem System die untergeordnete Version davon zuführt. Z.B. Ihre Anwendung unterstützt möglicherweise Plugins, und wenn ein Plugin Ihre sicherheitsrelevanten Klassen nur unterordnen kann, kann es diesen Trick verwenden, um eine untergeordnete Version davon irgendwie an ihren Platz zu schmuggeln. Dies ist jedoch eher etwas, mit dem sich Sun in Bezug auf Applets und dergleichen befassen muss, was möglicherweise nicht so realistisch ist.

Viel realistischer ist es zu vermeiden, dass ein Objekt veränderlich wird. Z.B. Da Strings unveränderlich sind, kann Ihr Code Verweise darauf sicher aufbewahren

 String blah = someOtherString;

anstatt zuerst die Zeichenfolge zu kopieren. Wenn Sie jedoch eine Unterklasse für String erstellen können, können Sie Methoden hinzufügen, mit denen der String-Wert geändert werden kann. Jetzt kann sich kein Code mehr darauf verlassen, dass der String derselbe bleibt, wenn er nur den String wie oben kopiert. Stattdessen muss er den duplizieren Zeichenfolge.

4
Mecki

Wenn Sie eine kommerzielle Closed-Source-Klasse schreiben, möchten Sie möglicherweise nicht, dass Benutzer die Funktionalität später ändern können. Dies gilt insbesondere dann, wenn Sie Unterstützung dafür benötigen und Benutzer Ihre Methode überschrieben haben und sich über den Aufruf dieser Klasse beschweren unerwartete Ergebnisse.

1
DavidG

Wenn Sie Klassen und Methoden als endgültig markieren, stellen Sie möglicherweise einen geringen Leistungszuwachs fest, da die Laufzeitumgebung nicht die richtige Klassenmethode nachschlagen muss, um ein bestimmtes Objekt aufzurufen. Nicht endgültige Methoden werden als virtuell markiert, damit sie bei Bedarf ordnungsgemäß erweitert werden können. Endgültige Methoden können direkt in der Klasse verknüpft oder inline kompiliert werden.

1
seanalltogether

Menschen davon abzuhalten, Dinge zu tun, die sie und andere verwirren könnten. Stellen Sie sich eine Physikbibliothek vor, in der Sie einige Konstanten oder Berechnungen definiert haben. Ohne das letzte Schlüsselwort könnte jemand kommen und grundlegende Berechnungen oder Konstanten neu definieren, die sich NIEMALS ändern sollten.

1
Anson Smith

Sie möchten eine Methode endgültig machen, damit das Überschreiben von Klassen ihr Verhalten nicht ändert. Wenn Sie in der Lage sein möchten, das Verhalten zu ändern, machen Sie die Methode öffentlich. Wenn Sie eine öffentliche Methode überschreiben, kann sie geändert werden.

0