web-dev-qa-db-ja.com

Javaのデフォルトコンストラクタ

ここで深刻な101の質問をしていることを知っています...

クラスFooBarを拡張するクラスFooがあります。 Fooには、フィールドに設定するパラメーターのセットを受け取るコンストラクターがあります。 Barなどの派生クラスは通常、これを変更する必要はありません。現在、私のIDEは私に与えています"Fooにはデフォルトのコンストラクタはありません"。それでは、すてきなのですが、派生クラスごとにこのコンストラクタを複製せずにこれを機能させるにはどうすればよいでしょうか?

51
Jeroen De Dauw

superコンストラクターを使用します。

public Bar(int a, double b, ...) {
    super(a, b, ...);
}
63
arshajii

それでは、すてきなものですが、派生クラスごとにこのコンストラクタを複製せずに、これをどのように動作させるのでしょうか?

サブクラスに同じシグネチャを持つコンストラクタを持たせる場合は、コンストラクタを複製する必要がありますsignatures-ただし、codeを複製する必要はありません-スーパークラスコンストラクターにチェーンするだけです:

public Bar(int x, int y) {
    super(x, y);
    // Any subclass-specific code
}

もちろん、differentのパラメーターセットからスーパークラスパラメーターを算出できる場合は、それで問題ありません。例えば:

public Bar(int x) {
    super(x, x * 2);
    // Any subclass-specific code
}

Barを構築するために必要な情報を把握する必要があります-thatはコンストラクタを決定する必要があります。

これが問題になる場合は、継承を使いすぎている可能性があります。あなたのactualクラスが何であるかを知らずに確実に言うのは難しいですが、継承の代わりに構成を使用することを検討する必要があります。万能薬ではありませんが、この種のことを回避できます。

17
Jon Skeet

いいえ、これ以上の「健全な」アプローチはありません。基本クラスにデフォルトのコンストラクターがない場合は、すべての子クラスから正しいコンストラクターを明示的に呼び出す必要があります。

これは、子クラスが基本クラスと同じコンストラクターexactを持つ必要があるという意味ではないことに注意してください。たとえば、これは完全に有効です。

class Foo {

    protected int a;
    protected int b;

    protected Foo(final int a, final int b) {
        this.a = a;
        this.b = b;
    }
}

class Bar extends Foo {

    protected Bar() {
        super(0,0);
    }
}
5
m0skit0

問題はこれで解決されます:

class Foo{
       Foo(int a, int b){}
}

class Bar extends Foo{
         //Here must be a constructor OR declare a constructor in Foo without parameters
         Bar(){super(1,1)} //this is an example

}

他の解決策は次のとおりです。

class Foo{
   Foo(int a, int b){}
   Foo(){}
}

class Bar extends Foo{
}

SuperClass(この場合はFoo)のパラメーターを持つコンストラクターがある場合、child class(この場合はBar)の暗黙的なコンストラクターは、常に"Super()"の暗黙的な呼び出し(明示的な場合を除き、常に1にする必要があります)。

3
Gaston Flores

このエラーは、最後にスーパーコンストラクターを呼び出しているためにも発生する可能性があります。最初のステートメントになるように移動する必要がある場合があります。

    public SectionsPagerAdapter(FragmentManager manager, List<Fragment> fragmentList) {
        mFragmentList  = fragmentList;
        super(manager);

    }

    public SectionsPagerAdapter(FragmentManager manager, List<Fragment> fragmentList) {
        super(manager); --> this should come first
        mFragmentList  = fragmentList;
    }
0
live-love

JVMは、設計上の理由によりコンストラクタを提供した場合、デフォルトのコンストラクタを提供しません。できることは、同じシグネチャでBarにコンストラクタを定義し、super()を呼び出します。

public Bar(int x,int y) {
    super(x,y);
}
0
Aniket Thakur

パラメータが不要な場合やデフォルト値がある場合は、デフォルトのコンストラクタを定義できます(パラメータなし):

class Foo
{
    public final int DEFAULT_A = 42;
    protected int a;
    protected int b;

    public Foo(final int a, final int b)
    {
        this.a = a;
        this.b = b;
    }

    // Is equal to new Foo(Foo.DEFAULT_A, 0);
    public Foo()
    {
        this.a = this.DEFAULT_A;
    }

}

class Bar extends Foo {}

class PiBar extends Bar
{
    public final int DEFAULT_A = Math.PI;

}
0
Vasilii Suricov