5

たとえば、クラスを拡張すると:

public class First {
    int id;
    public First(int _id) {
        id = _id;
    }
}

public class Second extends First {

}

同じことをする必要があるときは、Second クラスのコンストラクターを再宣言する必要があります。できます:

public Second(int _id) {
    super(_id);
}

しかし、親コンストラクターを変更するたびに、すべての拡張クラスのコンストラクターを編集する必要があります。

コンストラクターを完全に拡張するにはどうすればよいですか?

くそー、電話とアンテナについては言わないでください、私はOOPを何度も使用しました。

ここで質問するだけです。拡張クラスに public Class(){} を記述して、親コンストラクターを使用することはできませんか?

できないようです。わかった。

4

2 に答える 2

10

サブクラスを定義すると、スーパークラスからコンストラクターが継承されません。デフォルトのスーパークラス コンストラクター以外の場合は、各サブクラス コンストラクターで明示的にスーパークラス コンストラクターを呼び出す必要があります。(つまり、特に、基本クラスにデフォルト コンストラクターがない場合、すべての子クラス コンストラクターがスーパークラス コンストラクターを明示的に呼び出す必要がある子クラスもありません。また、子クラスは単にコンパイラによって生成されたデフォルト コンストラクターを持つことはできません。これには例外が 1 つあります。以下の[*]を参照してください。)

コンストラクターを継承すると、あらゆる種類の問題が発生する可能性があります。次のようなものを想像してください。

class Base {
    private int mId;
    public Base(int id) {
        mId = id;
    }
    . . .
}

ここで、never であることを確認したい 2 番目の属性 (タグ) を持つクラスを派生させたいと考えていますnull。したがって、次のように記述します。

class Derived extends Base {
    private Object mTag;
    public Derived(Object tag, int id) {
        super(id);
        if (tag == null) {
            throw new IllegalArgumentException("tag cannot be null");
        }
        mTag = tag;
    }
    . . .
}

Derived次のようなインスタンスを作成することを想像してください。

Derived derived = new Derived(3);

コンストラクターが継承された場合、これはおそらく合法です。それはどういう意味ですか?1 つには、mTagデフォルト値の に設定されますnull。のすべてのインスタンスにnull 以外のタグが必要Derivedであるという規則を強制する方法はありません。Derived

Java は、もう少し型付けが必要になる代わりに、コンストラクターの継承を正確に除外して、各クラスがそのインスタンスの作成方法を完全に制御できるようにします。

[*]コンパイラがデフォルト以外のコンストラクタを自動的に生成するケースが 1 つあります。Base上記のクラスと次のコードを検討してください。

Base foo = new Base(3) {
    . . . // some extended functionality
};

現在foo、 の無名サブクラスに初期化されていますBase。参照しやすいように、このサブクラスを と呼びましょうBase$Anon。コンパイラは、次と同等のコードを生成します。

class Base$Anon extends Base {
    Base$Anon(int id) {
        super(id);
    }
    . . . // some extended functionality
}

Base foo = new Base$Anon(3);

これは、独自のコンストラクターを指定しない場合に、コンパイラーがデフォルト以外のコンストラクターを生成する唯一のケースです。実際、言語構文では、匿名クラスのコンストラクターを宣言することさえできません。生成するコンパイラに依存する必要があります。

于 2012-05-20T16:30:27.743 に答える
2

この制限は、私が継承よりも合成を好む理由の 1 つです。代わりに、次のようなコードを使用することを検討してください。

public class Second {
    private final First first;

    public Second(final First first) {
         this.first=first;
    }

    public int getId() {
        return first.getId();
    }
}

私の意見では、この構成により、2 つのクラスの結合が少なくなり、クラス間の関係がより明確になります。継承よりも構成に関するより詳細な議論については、たとえば次の質問を参照してください: 継承よりも構成を優先しますか?

于 2012-05-20T16:24:56.533 に答える