2016-04-07 10 views
5

Ich verstehe, dass Konstruktor-Verkettung vom kleinsten Konstruktor zum größten Konstruktor geht. Zum BeispielKonstruktor Chaining ohne dies()

public MyChaining(){ 
     System.out.println("In default constructor..."); 
    } 
    public MyChaining(int i){ 
     this(); 
     System.out.println("In single parameter constructor..."); 
    } 
    public MyChaining(int i,int j){ 
     this(j); 
     System.out.println("In double parameter constructor..."); 
    } 

Auch als ich, dass der Anruf an this() und super() verstehe in der ersten Zeile sein muss. Aber ist es möglich (und wenn ja, ist es effizient), diese Limit- und Kettenkonstruktoren zu umgehen?

Zum Beispiel habe ich diese beiden Konstruktoren, die einige Code teilen.

public Location(String _Name) throws IOException, JSONException { 
     //Three lines of unique code (must be executed before the shared code) 
     //Shared code 
    } 

    public Location(JSONObject json) { 
     //Shared code 
    } 

Ist es in irgendeiner Weise möglich für den ersten Konstruktor, den zweiten zu nennen?

+0

@Philipp ja es ist und wird so gemacht werden. Ich habe mich nur gefragt, ob es durch Verkettung gemacht werden kann, weil ich anderswo keine Antwort finden konnte. – Akaitenshi

Antwort

4

Sicher. Wenn Sie eine static Funktion

JSONObject foo(String)

dann haben, können Sie

public Location(String _Name) throws IOException, JSONException { 
    this(foo(_Name)); 
} 
3

Die einzige Möglichkeit, gemeinsam genutzten Code ohne Aufruf von this auszuführen, besteht darin, dass beide Konstruktoren eine Initialisierungsmethode aufrufen, die den gemeinsamen Code enthält.

+0

Ja, ich weiß, dass es so gemacht werden kann. Ich habe mich gefragt, ob es durch Verkettung und nur getan werden kann. – Akaitenshi

+1

init() -Methode hat eine andere Schwierigkeit. Sie können letzte Instanzfelder in dieser Methode nicht initialisieren. –

+0

@Akaitenshi Die Verkettung erfolgt nur mit 'this();' und muss die erste Zeile des Konstruktors sein. – Eran

1

Eine irgendwie andere Antwort: Tu das nicht.

Konstruktoren sind wie alle anderen Mitglieder Ihrer Klasse - sie sollten "zusammen" sinnvoll sein. Konstruktoren, die dem Benutzer völlig "unterschiedliche" oder "unabhängige" "Schnittstellen" anbieten, sehen für mich wie ein Code-Geruch aus.

Sie sehen; wenn Sie eine Linie durch Ihre Klasse zeichnen können; und du findest, dass einige Elemente immer auf der linken Seite gehen und viele andere auf die rechte Seite dieser Linie gehen; Das ist ein Hinweis darauf, dass Sie Ihre Klasse vielleicht entlang dieser "Linie" teilen und stattdessen zwei Klassen erstellen sollten.

Wenn Sie wirklich die gleiche Art von Objekt aus verschiedenen Kontexten erstellen möchten; dann versuchen Sie, den "gemeinsamen Nenner Stück X" zu identifizieren; und stellen Sie einen Konstruktor für genau dieses X bereit. Und verwenden Sie dann Factory-Methoden, die diesen allgemeinen Konstruktor auf verschiedene Arten verwenden können. Dies bedeutet, dass Sie statische Methoden innerhalb derselben Klasse entweder bieten, wie

static Location generateLocationFromFoo(Foo foo) { ... } 
static Location generateLocationFromBar(Bar bar) { ... } 

Oder noch einen Schritt weiter gehen und eine separate Fabrik Klasse, die verwendet wird, um die tatsächliche Lage Objekte für Sie zu generieren.

+0

Es tut mir leid, aber ich verstehe Ihren letzten Satz nicht vollständig. Sie meinen, ich kann einen Konstruktor von einer Methode innerhalb derselben Klasse aufrufen und diese Methode verwenden, um mein Objekt zu instanziieren? – Akaitenshi

+0

Aktualisierte die Antwort; Ich hoffe, das hilft. – GhostCat

+0

Also würde ich den Konstruktor innerhalb 'generateLocation' aufrufen und 'objName.generateLocation()' auf meinem Haupt aufrufen oder wenn ich das Objekt möchte? – Akaitenshi

1

schreiben finde ich die Verkettung von der kleinsten Konstruktor zum größten Muster ziemlich unleserlich, da die tatsächliche Konstruktor Logik viele verteilt verschiedene Methoden.

finde ich es am meisten lesbar:

  • Haben Sie ein „main“ Konstruktor, der die Instanz Initialisierung vollständig behandelt
  • Haben alle anderen Konstrukteuren es nennen

auch etwas Ich mag nicht lange Verkettung (es ist schwierig, zum eigentlichen Code zu gelangen, wenn man von einem einfachen Konstruktor ausgeht), daher schreibe ich alle anderen Konstruktoren so, dass sie direkt "Haupt" nennen, außer es bedeutet doppelten Code.

Sie können immer umgehen die "this() Einschränkung muss die erste Anweisung sein" durch den Aufruf einer statischen Methode, es sei denn Sie versuchen, etwas zu tun, die diese Regel eigentlich verhindern will (z. B. ein halb initialisiertes Objekt verwenden). Beachten Sie, dass die aufgerufene Funktion genau statisch sein muss, damit Sie das halb initialisierte Objekt nicht verwenden können.