web-dev-qa-db-de.com

erweitert die Klasse mit privatem Konstruktor

Angenommen, wir haben den folgenden Code:

class Test {
    private Test() {
        System.out.println("test");
    }

}

public class One extends Test {

    One() {
        System.out.println("One");
    }

    public static void main(String args[]) {

        new One();
    }
}

Wenn wir ein Objekt One erstellen, wurde dies ursprünglich als Konstruktor der übergeordneten Klasse Test() bezeichnet. Da Test() jedoch privat war, erhalten wir einen Fehler. Wie viel ist ein gutes Beispiel und ein Ausweg aus dieser Situation?

43
user471011

Es gibt keinen Ausweg. Sie müssen einen verfügbaren Superkonstruktor (protected, public oder default) erstellen, um test erweitern zu können.

Diese Art der Notation wird normalerweise in Utility-Klassen oder Singletons verwendet, bei denen Sie nicht möchten, dass der Benutzer eine Instanz Ihrer Klasse erstellt, indem Sie sie erweitern und die Unterklasse instanziieren oder einfach einen Konstruktor Ihrer Klasse aufrufen.

Wenn Sie eine class mit nur private-Konstruktoren haben, können Sie die class auch in final ändern, da sie überhaupt nicht erweitert werden kann.


Eine andere Lösung wäre, eine Methode in test zu haben, die Instanzen von test erstellt und jeden Methodenaufruf von One an eine test-Instanz delegiert. Auf diese Weise müssen Sie test nicht erweitern.

class Test {
    private Test() {
        System.out.println("test");
    }
    public static Test getInstance(){
        return new Test();
    }
    public void methodA(){
        //Some kind of implementation
    }
}

public class One {
    private final Test test;
    One() {
        System.out.println("One");
        test = Test.getInstance();
    }

    public void methodA(){
        test.methodA();
    }

    public static void main(String args[]) {
        new One();
    }
}
43
Colin Hebert

Machen Sie den Konstruktor von test nicht -private oder verschieben Sie One in test.

Übrigens, Ihr Beispielcode enthält einige Probleme:

  • klassen sollten als Titelkoffer bezeichnet werden (Test statt test)
  • Ich würde vorschlagen, den Konstruktor One der Variable private zu erstellen, sofern er nicht von einer anderen Klasse im selben Paket aufgerufen wird
1
Mot

Eigentlich fand ich einen Ausweg. So was:

class Base {
    private Base() {

    }

    public void fn() {
        System.out.println("Base");
    }

    public static class Child extends Base {
        public void fn() {
            System.out.println("Child");
        }
    }

    public static Base getChild() {
        return new Child();
    }
}

Jetzt können Sie getChild () verwenden, um die Instanz der erweiterten Klasse abzurufen.

0
delphifirst