95

構造がこれに似ているいくつかの単純な Java コードがあります。

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

のかなりの数のサブクラスがあり、それぞれ独自BaseClassの方法でメソッドを実装します (テンプレート メソッド パターン)。getName()

これはうまく機能しますが、サブクラスに冗長なコンストラクターがあるのは好きではありません。タイプするのが多く、維持するのが難しいです。コンストラクターのメソッド シグネチャを変更する場合、BaseClassすべてのサブクラスを変更する必要があります。

サブクラスからコンストラクターを削除すると、次のコンパイル時エラーが発生します。

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

私がやろうとしていることは可能ですか?

4

12 に答える 12

148

このエラーが発生するのは、コンストラクターを持たないクラスにデフォルトのコンストラクターがあり、引数がなく、次のコードと同等であるためです。

public ACSubClass() {
    super();
}

ただし、BaseClass はコンストラクターを宣言するため (したがって、コンパイラーが提供するデフォルトの引数なしのコンストラクターがないため)、これは違法です。super();引数なしのコンストラクターがないため、BaseClass を拡張するクラスを呼び出すことはできません。ベースクラスで。

サブクラスには基本クラスが持つコンストラクターが自動的に含まれると考えるかもしれないので、これはおそらく少し直感に反します。

これを回避する最も簡単な方法は、基本クラスでコンストラクターを宣言しない (したがって、既定の引数なしコンストラクターを使用する) か、宣言された引数なしコンストラクターを (単独で、または他のコンストラクターと一緒に) 使用することです。しかし、多くの場合、このアプローチは適用できません。クラスの正当なインスタンスを構築するために、コンストラクターに渡される引数が必要になるためです。

于 2009-07-29T01:36:14.320 に答える
51

このエラーをグーグルで検索してここに到着した人のために:それを受け取る別の理由があるかもしれません。プロジェクトのセットアップ(システム構成の不一致)がある場合、Eclipseはこのエラーを出します。

たとえば、Java 1.7プロジェクトをEclipseにインポートし、1.7が正しく設定されていない場合、このエラーが発生します。次に、に移動しProject - Preference - Java - Compilerswitch to 1.6 or earlier; またはWindow - Preferences - Java - Installed JREs、JRE1.7インストールに移動して追加/修正します。

于 2013-02-19T20:30:13.393 に答える
8

それは可能ですが、あなたが持っている方法ではありません。

引数なしのコンストラクターを基本クラスに追加する必要があります。それだけです!

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

コンストラクター ( any ) をクラスに追加しない場合、コンパイラーはデフォルトの引数なしコンストラクターを追加します。

デフォルトの no arg が super(); を呼び出す場合。スーパークラスにそれがないため、そのエラーメッセージが表示されます。

それはそれ自体の質問です。

さて、答えを展開します:

異なる値 ( data ) を指定するためにサブクラス ( behavior ) を作成しても意味がないことに気付いていますか??!!! お願いします。

変更されるのが「名前」だけの場合は、パラメータ化された単一のクラスで十分です!

したがって、これは必要ありません:

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 コンストラクターのメソッド シグネチャを変更する場合、すべてのサブクラスを変更する必要があります。

そのため、継承は、OO システムでは望ましくない HIGH 結合を作成するアーティファクトです。それは避けるべきであり、おそらくコンポジションに置き換える必要があります。

サブクラスとして本当に必要かどうかを考えてください。そのため、以下のように使用されるインターフェースが頻繁に見られます。

 public interface NameAware {
     public String getName();
 }



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

ここで、B と C は A から継承され、それらの間で非常に高い結合が作成された可能性があります。インターフェースを使用することで結合が減少し、A が「NameAware」ではなくなると判断した場合、他のクラスは壊れません。

もちろん、動作を再利用したい場合、これは機能しません。

于 2009-07-29T01:35:36.350 に答える
2

もう 1 つの方法は、派生クラス コンストラクターの最初のステートメントとして、必要な引数を指定して super() を呼び出すことです。

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

public class Sub extends Sup {
    public Sub() { super("hello"); .. }
}
于 2014-06-08T22:51:56.663 に答える
0

サブクラスコンストラクターの最初のステートメントとしてスーパークラスコンストラクターへの呼び出しがない場合、Eclipse はこのエラーを出します。

于 2015-04-02T15:41:38.260 に答える
0

簡単な答え: base/parent/super クラスに引数のないコンストラクターを追加します。つまり、たとえば、

        class Parent{
    
    String name;
    int age;
    String occupation;
            //empty constructor
            public Parent(){
            
        }
    
    public Parent(String name, int age, String employment){
    this.name = name;
    this.age = age;
    this.occupation = employment;
    }
}

// 必要に応じて追加のコンストラクターを持つことができます。これは、親クラスでここでコンストラクターをオーバーロードすることです。

スーパークラスに引数のないコンストラクターがない場合、コンパイル時エラーが発生します。オブジェクトにはそのようなコンストラクタがあるため、オブジェクトが唯一のスーパー クラスであれば問題はありません。

// それでは継承しましょう

    class Child extends Parent{
              Child(String name, int age){
this.name = name;
this.age = age;
    }
    
    }

super() を使用すると、引数のないスーパー クラス コンストラクターが呼び出され、super(parameter list) を使用すると、一致するパラメーター リストを持つスーパー クラス コンストラクターが呼び出されます。

于 2021-01-23T20:06:28.490 に答える
-1

このエラーは、基本クラスに引数なしのコンストラクターを追加することで解決できます (以下を参照)。

乾杯。

 abstract public class BaseClass {
        // ADD AN ARGUMENTLESS CONSTRUCTOR TO THE BASE CLASS
        public 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";
    }
}
于 2013-08-20T21:17:51.297 に答える