405 Stimmen

Was ist falsch an überschreibbaren Methodenaufrufen in Konstruktoren?

Ich habe eine Wicket-Seitenklasse, die den Seitentitel in Abhängigkeit vom Ergebnis einer abstrakten Methode festlegt.

public abstract class BasicPage extends WebPage {

    public BasicPage() {
        add(new Label("title", getTitle()));
    }

    protected abstract String getTitle();

}

NetBeans warnt mich mit der Meldung "Overridable method call in constructor", aber was sollte daran falsch sein? Die einzige Alternative, die ich mir vorstellen kann, ist, die Ergebnisse von ansonsten abstrakten Methoden in Unterklassen an den Superkonstruktor zu übergeben. Aber das könnte bei vielen Parametern schwer zu lesen sein.

3voto

bvdb Punkte 18946

Ich stimme sicherlich zu, dass es Fälle gibt, in denen es ist besser, einige Methoden nicht über einen Konstruktor aufzurufen .

Sie machen privat beseitigt alle Zweifel: "Du sollst nicht passieren" .

Was aber, wenn Sie die Dinge offen halten wollen?

Es ist nicht nur den Zugangsmodifikator das ist das eigentliche Problem, wie ich zu erklären versucht habe aquí . Um ganz ehrlich zu sein, private ist ein klarer Showstopper, bei dem protected in der Regel noch eine (schädliche) Umgehung zulassen.

Ein eher allgemeiner Ratschlag:

  • Starten Sie keine Threads von Ihrem Konstruktor aus
  • lesen Sie keine Dateien aus Ihrem Konstruktor
  • Rufen Sie keine APIs oder Dienste von Ihrem Konstruktor aus auf.
  • Laden Sie keine Daten aus einer Datenbank über Ihren Konstruktor
  • parsen Sie keine json oder xml Dokumente von Ihrem Konstruktor

Tun Sie dies nicht (in)direkt von Ihrem Konstruktor aus. Das schließt ein, dass Sie eine dieser Aktionen von einer privaten/geschützten Funktion aus durchführen, die vom Konstruktor aufgerufen wird.

Aufrufen einer start() Methode aus Ihrem Konstruktor könnte ein Warnsignal sein.

Stattdessen sollten Sie eine öffentlich init() , start() o connect() Methode. Und überlassen Sie die Verantwortung dem Verbraucher.

Einfach ausgedrückt: Sie wollen getrennt der Moment des " Vorbereitung " aus dem " Zündung ".

  • Wenn ein Konstruktor erweitert werden kann, sollte er sich nicht selbst entzünden.
  • Wenn sie sich selbst entzündet, besteht die Gefahr, dass sie gestartet wird, bevor sie fertig gebaut ist.
  • Schließlich könnte eines Tages mehr Vorbereitung im Konstruktor einer Unterklasse hinzugefügt werden. Und Sie haben keine Kontrolle über die Reihenfolge der Ausführung des Konstruktors einer Oberklasse.

PS: Erwägen Sie die Implementierung der Verschließbar Schnittstelle mit.

2voto

Volksman Punkte 1901

Im konkreten Fall von Wicket: Dies ist der Grund, warum ich die Wicket Entwickler gebeten, Unterstützung für einen expliziten zweiphasigen Komponenteninitialisierungsprozess in den Lebenszyklus des Frameworks zur Erstellung einer Komponente hinzuzufügen, d.h.

  1. Konstruktion - über Konstrukteur
  2. Initialisierung - über onInitilize (nach der Konstruktion, wenn virtuelle Methoden funktionieren!)

Es gab eine recht lebhafte Debatte darüber, ob dies notwendig war oder nicht (es ist IMHO durchaus notwendig), wie dieser Link zeigt http://apache-wicket.1842946.n4.nabble.com/VOTE-WICKET-3218-Component-onInitialize-is-broken-for-Pages-td3341090i20.html )

Die gute Nachricht ist, dass die exzellenten Entwickler von Wicket die Einführung der Zwei-Phasen-Initialisierung beendet haben (um das großartigste Java UI-Framework noch großartiger zu machen!), so dass Sie mit Wicket die gesamte Initialisierung nach der Konstruktion in der onInitialize-Methode durchführen können, die vom Framework automatisch aufgerufen wird, wenn Sie sie überschreiben - an diesem Punkt im Lebenszyklus Ihrer Komponente hat der Konstruktor seine Arbeit abgeschlossen, so dass die virtuellen Methoden wie erwartet funktionieren.

0voto

sanluck Punkte 1514

Ich denke, für Wicket ist es besser, anzurufen add Methode in der onInitialize() (siehe Lebenszyklus der Komponenten ) :

public abstract class BasicPage extends WebPage {

    public BasicPage() {
    }

    @Override
    public void onInitialize() {
        add(new Label("title", getTitle()));
    }

    protected abstract String getTitle();
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X