Frage

Angenommen, ich eine Basisklasse B haben, und eine abgeleitete Klasse D. Ich möchte eine Methode foo () in meiner Basisklasse haben, der die Instanz ein neues Objekt wie auch immer geartete zurückgibt. So zum Beispiel, wenn I B.foo () aufrufen, es gibt ein Objekt vom Typ B, während, wenn I D.foo () aufrufen es ein Objekt des Typs D zurückkehrt; Inzwischen befindet sich die Umsetzung ausschließlich in der Basisklasse B.

Ist das möglich?

War es hilfreich?

Lösung

Nicht. Machen Sie das "foo" Methode abstrakt.

abstract class B {
    public abstract B foo();
}

oder eine abstrakte Fabrik durch den Basisklassenkonstruktor erhalten:

abstract class B {
    private final BFactory factory;
    protected B(BFactory factory) {
        this.factory = factory;
    }
    public B foo() {
        return factory.create();
    }
}
interface BFactory {
    B create();
}

In kovarianten Rückgabetypen und Generika zu schmecken.

Andere Tipps

Solange jede Klasse einen Standardkonstruktor hat:

    public B instance() throws Exception {
        return getClass().newInstance();
    }

Nun, ich könnte weg sein, aber ich würde davon ausgehen, dass da „das“ bezieht sich immer auf das aktuelle Objekt, Sie so etwas wie

tun könnte
public B foo() {
    return this.getClass().newInstance();
}

oder etwas in diese Richtung? Wenn Sie eine Instanz von D erstellen und dann d.foo () aufrufen, sollten Sie eine Instanz von D bekommen als B. zurückgegeben Sie es als einfaches Objekt zurückkehren könnte, aber Sie sollten in diesem Fall so spezifisch wie möglich sein, denke ich.

Neben der Tatsache, dass ich denke, dass es wahrscheinlich ein Konstruktionsfehler ist, wenn Sie diese erreichen möchten, können Sie den folgenden Ansatz versuchen.

In Ihrer Frage, verwenden Sie statische (Klassen-) Methoden, B.foo (), D.foo (), dies nicht erreicht Vererbung werden kann, weil die statischen Methoden keine Dynamik haben, nehmen sie nicht Teil in dem Look-up-System. So dass Sie nicht genug Typinformationen haben.

Wenn Sie eine Member-Funktion foo () verwenden könnten Sie das folgende Konstrukt haben:

public class B {
    public B foo()
    throws IllegalAccessException, InstantiationException {
        return this.getClass().newInstance();
    }
}

public class D  extends B{    
}

public class Test {
    public static final void main(String[] args)
    {
        try {
            System.out.println((new B()).foo());
            System.out.println((new D()).foo());
        } catch (IllegalAccessException e) {
            e.printStackTrace();  
        } catch (InstantiationException e) {
            e.printStackTrace();  
        }
    }
}

Wie die anderen Antworten sagen, können Sie getClass (). NewInstance (), wenn es einen Konstruktor ohne Argumente ist in jeder Unterklasse (stellen Sie sicher, InstantiationException und Illegal zu fangen).

Wenn eine der Konstrukteurs-Argumente benötigen, können Sie entweder Reflexion oder (bevorzugt aus meiner Sicht) definieren eine Methode, wie getNewInstance (), die Sie in der Unterklasse überschreiben können, nur wenn nötig.

z.

Thing foo() {
    Thing th = getNewInstance();
    // do some stuff with th
    return th;
}

Thing getNewInstance() {
    return getClass().newInstance();
}

Dann getNewInstance () kann nur außer Kraft gesetzt werden, wenn Sie wirklich brauchen, für Unterklassen, die den Standardkonstruktor nicht haben.

Thing getNewInstance() {
    return new BigThing(10, ThingSize.METRES);
}

ich denke, das möglich sein könnte, Reflexion, das heißt in der Superklasse zu tun, verwenden Sie haben:

public ClassName getFoo() throws InstantiationException, IllegalAccessException
{
    return getClass().newInstance();
}

Wo Klassenname der Name Ihrer Basisklasse ist.

Sie werden es werfen, wo immer Sie es wollen, obwohl die Verwendung ... Ich bin nicht sicher, ob dies wirklich eine gute Lösung!

Edit:. newInstance () Typ Methoden in der Regel statisch sind, und natürlich werden Sie nicht eine Vorstellung davon haben, was die Art der Unterklasse ist mit einer statischen Methode

Das glaube ich nicht, dass es eine Möglichkeit, sich einen statisch Methode (dynamisch) eine Instanz einer Unterklasse.

@Rik

Nun, das eigentliche Problem ist, dass ich eine abstrakte Basisklasse Sache haben. Und Ding hat eine Methode namens getNextThing (), die eine neue Instanz der Sache zurück.

Dann habe ich eine Reihe von Unterklassen wie BigThing, littlething, SomethingThing, und ich will nicht zu halten, die getNextThing () -Methode für jeden von ihnen neu zu schreiben. Es scheint, verschwenderisch, da sie alle das gleiche tun ... Sache.

Bin ich falsch in meinem Ansatz?

Ich bin mir nicht sicher, warum Sie versuchen zu tun, was Sie wirklich zu tun versuchen. mehr eines Kontextes Providing könnte lassen Sie sich mehr Hilfe geben.

public class B <X extends B>{

public X foo() throws InstantiationException, IllegalAccessException{
    return (X)this.getClass().newInstance();
}
}        
public class C extends B<C>{        

}

Lassen Sie mich Ihnen diesen Rat bieten. Die Art und Weise CS-Klassen sind in der Regel gelehrt werden, dass Professoren mit Vererbung verliebt sind, aber noch nicht Zusammensetzung herausgefunden. Ich denke, was Sie vielleicht suchen Zusammensetzung. Anstatt also Aufruf getNextThing auf die Sache selbst, vielleicht sollten Sie darüber nachdenken, machen Thing implementieren Iterable

Das heißt, dass Sie nur ein

scroll top