Ошибка Java: Неявный суперконструктор не определен для конструктора по умолчанию

Если Вы думаете о методах, обратился к объектам как к статическим методам, которые передают неявное' this' в функцию, она может сделать взгляды OO в C легче.

, Например:

String s = "hi";
System.out.println(s.length());

становится:

string s = "hi";
printf(length(s)); // pass in s, as an implicit this

Или что-то как этот.

87
задан Jeff Axelrod 12 April 2012 в 16:41
поделиться

3 ответа

You get this error because a class which has no constructor has a default constructor, which is argument-less and is equivalent to the following code:

public ACSubClass() {
    super();
}

However since your BaseClass declares a constructor (and therefore doesn't have the default, no-arg constructor that the compiler would otherwise provide) this is illegal - a class that extends BaseClass can't call super(); because there is not a no-argument constructor in BaseClass.

This is probably a little counter-intuitive because you might think that a subclass automatically has any constructor that the base class has.

The simplest way around this is for the base class to not declare a constructor (and thus have the default, no-arg constructor) or have a declared no-arg constructor (either by itself or alongside any other constructors). But often this approach can't be applied - because you need whatever arguments are being passed into the constructor to construct a legit instance of the class.

144
ответ дан 24 November 2019 в 07:45
поделиться

Это возможно, но не так, как у вас.

Вы должны добавить конструктор без аргументов к базовому классу, и все!

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";
    }
}

Когда вы не добавляете конструктор (любой) к классу компилятор добавляет для вас конструктор no arg по умолчанию.

Когда defualt no arg вызывает super (); и так как у вас его нет в суперклассе, вы получите то сообщение об ошибке.

Это касается самого вопроса.

Теперь расширяем ответ:

Вы знаете, что создание подкласса (поведения) для указания другого значения (данных) не имеет смысла ?? !!! Я надеюсь, что вы это сделаете.

Если единственное, что меняет, - это "имя", тогда достаточно одного параметризованного класса!

Так что вам это не нужно:

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

или

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

Когда вы можете написать этот:

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

Если бы мне пришлось изменить сигнатуру метода конструктора BaseClass, мне пришлось бы изменить все подклассы.

Итак, наследование - это артефакт, который создает HIGH-связь, что нежелательно в объектно-ориентированных системах. Этого следует избегать и, возможно, заменить композицией.

Подумайте, действительно ли они вам действительно нужны как подкласс. Вот почему вы часто видите, что интерфейсы используются insted:

 public interface NameAware {
     public String getName();
 }



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

Здесь B и C могли унаследовать от A, что создало бы очень ВЫСОКУЮ связь между ними, при использовании интерфейсов связь уменьшается, если A решит, что она больше не будет " NameAware "другие классы не сломаются.

Конечно, если вы хотите повторно использовать поведение, это не сработает.

s почему наследование - это артефакт, который создает ВЫСОКОЕ сцепление, что нежелательно в объектно-ориентированных системах. Этого следует избегать и, возможно, заменить композицией.

Подумайте, действительно ли они вам действительно нужны как подкласс. Вот почему вы часто видите, что интерфейсы используются insted:

 public interface NameAware {
     public String getName();
 }



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

Здесь B и C могли унаследовать от A, что создало бы очень ВЫСОКУЮ связь между ними, при использовании интерфейсов связь уменьшается, если A решит, что она больше не будет " NameAware "другие классы не сломаются.

Конечно, если вы хотите повторно использовать поведение, это не сработает.

s почему наследование - это артефакт, который создает ВЫСОКОЕ сцепление, что нежелательно в объектно-ориентированных системах. Этого следует избегать и, возможно, заменить композицией.

Подумайте, действительно ли они вам действительно нужны как подкласс. Вот почему вы часто видите, что интерфейсы используются insted:

 public interface NameAware {
     public String getName();
 }



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

Здесь B и C могли унаследовать от A, что создало бы очень ВЫСОКУЮ связь между ними, при использовании интерфейсов связь уменьшается, если A решит, что она больше не будет " NameAware "другие классы не сломаются.

Конечно, если вы хотите повторно использовать поведение, это не сработает.

 public interface NameAware {
     public String getName();
 }



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

Здесь B и C могли унаследовать от A, что создало бы очень ВЫСОКУЮ связь между ними, при использовании интерфейсов связь уменьшается, если A решает, что он больше не будет «NameAware», другие классы не сломаются.

Конечно, если вы хотите повторно использовать поведение, это не сработает.

 public interface NameAware {
     public String getName();
 }



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

Здесь B и C могли унаследовать от A, что создало бы очень ВЫСОКУЮ связь между ними, при использовании интерфейсов связь уменьшается, если A решает, что он больше не будет «NameAware», другие классы не сломаются.

Конечно, если вы хотите повторно использовать поведение, это не сработает.

7
ответ дан 24 November 2019 в 07:45
поделиться

вашему BaseClass требуется someString, поэтому доставит один.
Попробуйте следующее:

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";
    }
}

или

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
ответ дан 24 November 2019 в 07:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: