webentwicklung-frage-antwort-db.com.de

Java-Fehler: Der implizite Superkonstruktor ist für den Standardkonstruktor nicht definiert

Ich habe einen einfachen Java-Code, der in seiner Struktur ähnlich aussieht:

abstract public class BaseClass {
    String someString;
    public BaseClass(String someString) {
        this.someString = someString;
    }
    abstract public String getName();
}

public class ACSubClass extends BaseClass {
    public ASubClass(String someString) {
        super(someString);
    }
    public String getName() {
        return "name value for ASubClass";
    }
}

Ich werde einige Unterklassen von BaseClass haben, von denen jede die Methode getName() auf ihre eigene Weise implementiert ( Template-Methodenmuster ).

Das funktioniert gut, aber ich mag es nicht, den redundanten Konstruktor in den Unterklassen zu haben. Es ist mehr zu tippen und es ist schwierig zu warten. Wenn ich die Methodensignatur des Konstruktors BaseClass ändern würde, müsste ich alle Unterklassen ändern.

Wenn ich den Konstruktor aus den Unterklassen entferne, wird beim Kompilieren folgender Fehler angezeigt:

Implicit super constructor BaseClass() is undefined for default constructor. Must define an explicit constructor

Ist das, was ich versuche, möglich?

85
Joel

Sie erhalten diesen Fehler, weil eine Klasse, die keinen Konstruktor hat, einen default - Konstruktor hat, der ohne Argument ist und dem folgenden Code entspricht:

public ACSubClass() {
    super();
}

Da Ihre BaseClass jedoch einen Konstruktor deklariert (und daher nicht den Standardkonstruktor no-arg besitzt, den der Compiler andernfalls bereitstellen würde), ist dies illegal. Eine Klasse, die BaseClass erweitert, kann super(); nicht aufrufen, da kein Argument vorhanden ist Konstruktor in BaseClass.

Dies ist wahrscheinlich ein wenig kontrapunktisch, weil Sie denken, dass eine Unterklasse automatisch über einen Konstruktor verfügt, den die Basisklasse hat.

Der einfachste Weg, dies zu erreichen, besteht darin, dass die Basisklasse keinen Konstruktor deklariert (und somit den Standardkonstruktor no-arg besitzt) oder einen deklarierten Konstruktor no-arg (entweder von sich selbst oder neben anderen Konstruktoren) hat. Diese Methode kann jedoch häufig nicht angewendet werden. Sie benötigen die Argumente, die an den Konstruktor übergeben werden, um eine legitime Instanz der Klasse zu erstellen.

140
matt b

Für diejenigen, die Google für diesen Fehler und hier ankommen: Es könnte einen anderen Grund geben, um ihn zu erhalten. Eclipse gibt diesen Fehler aus, wenn Projektkonfiguration und Systemkonfiguration nicht übereinstimmen.

Wenn Sie zum Beispiel ein Java 1.7-Projekt in Eclipse importieren und 1.7 nicht ordnungsgemäß eingerichtet haben, wird dieser Fehler angezeigt. Dann können Sie entweder zu Project - Preference - Java - Compiler und switch to 1.6 or earlier wechseln. oder gehen Sie zu Window - Preferences - Java - Installed JREs und fügen Sie Ihre JRE 1.7-Installation hinzu bzw. beheben Sie sie.

43
MF.OX

Es ist möglich, aber nicht so, wie Sie es haben.

Sie müssen einen No-Args-Konstruktor zur Basisklasse hinzufügen und fertig!

public abstract class A {
    private String name;
    public A(){
        this.name = getName();
    }
    public abstract String getName();


    public String toString(){
        return "simple class name: " + this.getClass().getSimpleName() + " name:\"" + this.name + "\"";
    }
}
class B extends A {
    public String getName(){
        return "my name is B";
    }
    public static void main( String [] args ) {
        System.out.println( new C() );
    }
}
class C extends A {
    public String getName() {
        return "Zee";
    }
}

Wenn Sie keiner Klasse einen Konstruktor hinzufügen, fügt der Compiler den Standard-Konstruktor no arg für Sie hinzu.

Wenn das defualt kein arg zu super () aufruft; und da Sie es nicht in der Superklasse haben, erhalten Sie diese Fehlermeldung.

Es geht um die Frage selbst. 

Nun erweitern Sie die Antwort:

Ist Ihnen bewusst, dass das Erstellen einer Unterklasse (Verhalten) zum Angeben eines anderen Werts (Daten) keinen Sinn macht? !!! Ich hoffe du tust.

Wenn sich nur der "Name" ändert, genügt eine einzige parametrisierte Klasse!

Also brauchst du das nicht:

MyClass a = new A("A");
MyClass b = new B("B");
MyClass c = new C("C");
MyClass d = new D("D");

oder 

MyClass a = new A(); // internally setting "A" "B", "C" etc.
MyClass b = new B();
MyClass c = new C();
MyClass d = new D();

Wenn du das schreiben kannst:

MyClass a = new MyClass("A");
MyClass b = new MyClass("B");
MyClass c = new MyClass("C");
MyClass d = new MyClass("D");

Wenn ich die Methodensignatur des BaseClass-Konstruktors ändern würde, müsste ich alle Unterklassen ändern.

Deshalb ist Vererbung das Artefakt, das eine HIGH-Kopplung erzeugt, was in OO - Systemen unerwünscht ist. Es sollte vermieden und vielleicht durch Komposition ersetzt werden.

Überlegen Sie, ob Sie sie wirklich wirklich als Unterklasse brauchen. Aus diesem Grund sehen Sie sehr häufig Schnittstellen, die insted verwendet werden:

 public interface NameAware {
     public String getName();
 }



 class A implements NameAware ...
 class B implements NameAware ...
 class C ... etc. 

Hier hätten B und C von A geerbt werden können, was zu einer sehr hohen Kopplung zwischen ihnen geführt hätte. Durch die Verwendung von Schnittstellen wird die Kopplung reduziert. Wenn A entscheidet, dass es nicht mehr "NameAware" ist, werden die anderen Klassen nicht kaputt gehen.

Wenn Sie Verhalten wiederverwenden möchten, funktioniert dies natürlich nicht. 

7
OscarRyz

Sie können diesen Fehler auch erhalten, wenn JRE nicht gesetzt ist. Wenn dies der Fall ist, fügen Sie Ihrem Projekt JRE System Library hinzu.

Unter Eclipse IDE:

  1. Öffnen Sie das Menü Projekt -> Eigenschaften oder klicken Sie mit der rechten Maustaste auf Ihr Projekt in Package Explorer und wählen Sie Eigenschaften (Alt + Eingabe unter Windows, Befehl + I auf Mac).
  2. klicken Sie auf Java Build Path und dann auf Libraries
  3. wählen Sie ModulPfad oder Classpath und drücken Sie die Taste Add Library ...
  4. wählen Sie JRE System Library aus und klicken Sie auf Next.
  5. lassen Sie Workspace default JRE ausgewählt (Sie können auch eine andere Option verwenden) und klicken Sie auf Fertig stellen.
  6. drücken Sie schließlich Apply und Close.
1
yogesh kumar

Eclipse gibt diesen Fehler aus, wenn Sie den Superklassenkonstruktor nicht als erste Anweisung im Unterklassenkonstruktor aufgerufen haben.

0
Sagar

ihre BaseClass benötigt einen someString, also deliver.
Versuche dies: 

abstract public class BaseClass {
    String someString;
    public BaseClass(String someString) {
        this.someString = someString;
    }
    abstract public String getName();
}

public class ACSubClass extends BaseClass {
    public ASubClass() {
        super("someString");  // or a meaningfull value, same as getName()?
    }
    public String getName() {
        return "name value for ASubClass";
    }
}

oder 

abstract public class BaseClass {
    String someString;
    protected BaseClass() {  // for subclasses
        this.someString = null;  // or a meaningfull value
    }
    public BaseClass(String someString) {
        this.someString = someString;
    }
    abstract public String getName();
}

public class ACSubClass extends BaseClass {
    public String getName() {
        return "name value for ASubClass";
    }
}
0

Eine andere Möglichkeit ist der Aufruf von super () mit dem erforderlichen Argument als erste Anweisung im Konstruktor für abgeleitete Klassen.

public class Sup {
    public Sup(String s) { ...}
}

public class Sub extends Sup {
    public Sub() { super("hello"); .. }
}
0
user2407102

Tut mir leid für die Nekropostierung, stand aber heute vor diesem Problem. Für alle, die ebenfalls mit diesem Problem konfrontiert sind - einer der möglichen Gründe - rufen Sie nicht super in der ersten Zeile der Methode auf. Zweite, dritte und andere Zeilen lösen diesen Fehler aus. Der Aufruf von Super sollte der allererste Aufruf in Ihrer Methode sein. In diesem Fall ist alles gut.

0
Serj.by