Javaエラー:暗黙のスーパーコンストラクターがデフォルトコンストラクターに対して未定義です


88

私はその構造がこれに似たいくつかの単純な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

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


1
「冗長な」コンストラクタを残してください!コードの読みやすさを維持し、すべての最新のIDEで自動的に作成できるため、ショートカットを入力するだけで済みます。
Andreas Dolk

3
1年後に自分の質問をもう一度読んでみると、matt bのようなコンストラクター(基本クラスを含む)を削除してから、静的ファクトリーメソッドを使用してインスタンスを作成することができました。
ジョエル

回答:


145

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

public ACSubClass() {
    super();
}

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

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

これを回避する最も簡単な方法は、基本クラスがコンストラクターを宣言しない(つまり、デフォルトの引数なしのコンストラクターを持つ)か、引数なしのコンストラクターを宣言する(それ自体、または他のコンストラクターと一緒に)ことです。しかし、多くの場合、このアプローチは適用できません。クラスの正当なインスタンスを構築するには、コンストラクタに渡される引数が必要だからです。


17
「サブクラスには、基本クラスのコンストラクターが自動的に含まれていると思うかもしれないので、これはおそらく少し直感に反します。」+1
Mr_and_Mrs_D 2013

2
後世のために、私は将来の読者のために私の解決策を提案します。引数なしのコンストラクタを作成しますが、BaseClass単にUnsupportedOperationException何かをスローするようにします。これは最良の解決策ではありません(クラスが引数なしのコンストラクタをサポートできることを誤って示唆しています)が、私が考えることができる最良の解決策です。
JMTyler 2015

49

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

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


2
Eclipseに明らかな理由がないため、このエラーが発生しました。次に、ワークスペースをクリーンアップし(メニュープロジェクト->クリーン...)、それが消えました。
erickrf 2014

7

それは可能ですが、あなたのやり方ではありません。

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

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)を追加しない場合、コンパイラーはデフォルトの引数なしのコンストラクターを追加します。

デフォルトでは、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から非常に高いカップリングを作成します。インターフェースを使用することにより、カップリングは減少します。

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


2
はい。ただし、インスタンスが適切に初期化されていることを確認できなくなった場合(例:この特定のケースでは名前が付けられている場合)
ChssPly76

@ ChssPly76:はい、しかし、それはおそらく継承がうまく利用されていないためです。私はそれをカバーするために私の答えを拡大しました。
OscarRyz 2009

4

JREが設定されていない場合にも、このエラーが発生する可能性があります。その場合は、JREシステムライブラリをプロジェクトに追加してみてください。

Eclipse IDEの場合:

  1. メニュープロジェクト -> プロパティを開くか、パッケージエクスプローラーでプロジェクトを右クリックして、プロパティ(WindowsではAlt + Enter、MacではCommand + I)を選択します。
  2. クリックしてJavaのビルド・パス、その後ライブラリ ]タブ
  3. ModulepathまたはClasspathを選択し、Add Library ...ボタンを押します
  4. JREシステムライブラリを選択し、[ 次へ ]をクリックします。
  5. キープワークスペースのデフォルトJREを選択(あなたはまた、別のオプションを取ることができます)をクリックし、完了を
  6. 最後に[適用して閉じる]を押します

2

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

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

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

0

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


0

ネクロポスティングで申し訳ありませんが、今日この問題に直面しました。誰もがこの問題に直面している-考えられる理由の1つ- superメソッドの最初の行では呼び出さない。2番目、3番目、およびその他の行でこのエラーが発生します。superの呼び出しは、メソッドの最初の呼び出しでなければなりません。この場合、すべてが順調です。


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

これにより、無効なオブジェクト(を持たないオブジェクトsomeString)セットを簡単に構築できるため、コンストラクターとしての目的が完全に無効になります。
ロバート

-1

私はこのエラーが発生し、メソッドの横からtry / catchブロックにスローされた例外を削除することで修正しました

例:FROM:

public static HashMap<String, String> getMap() throws SQLException
{

}

に:

public static Hashmap<String,String> getMap()
{
  try{

  }catch(SQLException)
  { 
  }
}

この答えは、不足しているコンストラクターのコンパイラエラーとは関係ありません。
ロバート
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.