2016-07-15 42 views
1

Ich fand eine Menge Post zu dem Thema, konnte aber nicht die Lösung finden, nach der ich suchte.Wie gebe ich den Rückgabetyp der Methode einer abstrakten Klasse an

So, hier ist der Deal:

Ich habe eine erste abstrakte Klasse mit zwei Unterklassen:

public abstract class A { 
    public A(args){..} 
} 
public class B extends A { 
    public B(args){ 
    super(args); 
    } 
} 
public class C extends A{ 
    public C(args){ 
    super(args); 
    } 
} 

args einige Variablen sind aber in Form nicht ändert. Einige andere Sachen sind in den Klassen, aber es spielt hier keine Rolle.

Nun, ich habe eine andere abstrakte Klasse mit zwei Unterklassen, die Bauherren für B und C sind Der größte Teil der Erbauer ist die gleiche, also würde ich es in dem abstrakten Baumeister sein mag

public abstract class Builder { 
    public A build(*?*){ 
    //compute args 
    return new *either B or C*(args); 
    } 
} 
public class B_Builder extends Builder { 
    public B build(*?*){ 
    super(*?*); 
    } 
} 
public class C_Builder extends Builder{ 
    public C build(*?*){ 
    super(*?*); 
    } 
} 

Noch einmal, das andere Zeug in den Bauherren spielt keine Rolle.

Meine Frage ist, wie Sie der Builder-Klasse abastract mitteilen, wie der Rückgabetyp des Builds über die Builder-Unterklasse sein soll. Wissen, dass die Rückgabetyp B und C beide erweitert A. Ich denke, ich sollte einige allgemeine Sachen verwenden, aber ich kann es nicht schaffen, es zu arbeiten.

Kann mir jemand helfen?

Vielen Dank!

LD

+0

Akzeptiert 'build()' irgendwelche Argumente? Wie viele Argumente haben die Konstruktoren? – shmosel

+0

'build()' benötigt mindestens ein Argument (die Klasse, die die Daten enthält, die für den Build benötigt werden), aber es könnte auch andere haben. Der Konstruktor benötigt ungefähr 10 Argumente, die aus dem Argument von 'build()' stammen. Ihre Lösung hat den Trick übrigens, vielen Dank !!!! Ich werde auch die anderen versuchen, um ein bisschen mehr über Generika zu lernen. – ldebroux

+0

können Sie Fabrikmuster und Uhr * Polymorphismus * handeln verwenden – emotionlessbananas

Antwort

1

Sie können es mit einem generischen Typparameter tun und einer abstrakten Konzept Methode, die die Konstruktion hat, während die abstrakte Klasse, das schwere Heben tut:

public abstract class Builder<T extends A> { 
    public T build(*?*){ 
    //compute args 
    return create(args); 
    } 

    protected abstract T create(args); 
} 

public class B_Builder extends Builder<B> { 
    @Override 
    protected B create(args) { 
    return new B(args); 
    } 
} 

public class C_Builder extends Builder<C>{ 
    @Override 
    protected C create(args) { 
    return new C(args); 
    } 
} 
0

Ja, Sie sind nah genug, generisch ist der Weg zu gehen:

A:

public abstract class A <T extends A<?>>{ 

    public abstract T getObject(Object args); 
} 

B:

public class B extends A<B>{ 

     @Override 
     public B getObject(Object args) { 
      // TODO Auto-generated method stub 
      return null; 
     } 

    } 

C:

public class C extends A<C>{ 

    @Override 
    public C getObject(Object args) { 
     // TODO Auto-generated method stub 
     return null; 
    } 


} 
-1

können Sie verlassen nur eine Builder mit einer einzelnen Buildmethode wie dieser:

public class BuilderA { 
public static <T extends A> T of(Class<T> type, Object arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { 
    Constructor<T> constructor = type.getConstructor(arg.getClass()); 
    return constructor.newInstance(arg); 
} 
} 

Diese Methode verwendet Reflektion, um eine Instanz mit dem angegebenen Typ zu erstellen. Er geht davon aus, dass die gleiche Art von Parametern im Konstruktor der Klassen A, B und C. Hier verwendet wird, wie ein Anruf aussehen würde:

A a1 = BuilderA.of(B.class, 1);   
    A a2 = BuilderA.of(C.class, 2); 
    B b = BuilderA.of(B.class, 2); 
    C c = BuilderA.of(C.class, 2); 

In den obigen Anrufen, alle Klassen haben einen Konstruktor mit der Typ Integer. Wenn Sie mehrere Argumente haben, können Sie varargs als letzten Parameter verwenden und die Klassen von vararg abrufen und sie zum Abrufen des richtigen Konstruktors verwenden.

+0

Warum der Downvote? – Slimu

0

Fügen Sie dem Builder für Superklasse einen Vorlagenparameter hinzu.

class Builder<T> { 
    T build() {} 
} 

Dann, wenn Sie den Einsatz so etwas wie

class ABuilder extends Builder<A> { 
     A build() {} 
    } 

    class BBuilder extends Builder<B> { 
     B build() {} 
    } 

Voll Code mit einem Arbeitsbeispiel in Codiva online compiler IDE erweitern.

0

Ich schlage vor, den gleichen Teil zu einer einzigen Methode zu legen, und die Erstellungscodes von B und C sollten in den Unterbauern sein.

public abstract class Builder<T> { 
    public abstract T create(args); 
    public void build(args){ 
    //do something here 
    return create(args); 
    } 
} 
public class BBuilder extends Builder<B> { 
    @Override 
    public B create(int args) { 
    return new B(args); 
    } 
}