0

基本クラスには、ArrayList として実装された変数があります。

class Base<E> {

    List<Collection<E>> adj;

    public Base (int size) {
        adj = new ArrayList<Collection<E>>(size);
        for(int i = 0; i < size; i++)
            adj.add(new ArrayList<E>());
    }
}

サブクラスで、実装を HashSet に変更したいと思います。

class Sub<E> extends Base<E> {

    List<Collection<E>> adj;

    public Sub (int size) {
        adj = new ArrayList<Collection<E>>(size);
        for(int i = 0; i < size; i++)
            adj.add(new HashSet<E>());
    }
}

しかし、「別のコンストラクターを明示的に呼び出す必要があります」というエラーが表示されるため、許可されません。私は何をすべきか?

4

3 に答える 3

1

一部の人々は質問に答えていますが、より重要で重要なポイントを見逃しています:基本クラスのメンバーをシャドウしないでください! そうする正当な理由があるまれな状況が 1 つか 2 つあるかもしれませんが、私には思いつきません。初心者にありがちなミスですが。

問題を簡単に説明するには:

private static class Foo {
    protected int x = 1;
}

private static class Bar extends Foo {
    protected int x = 0;
}

public static void main(String[] args) {
    Bar b = new Bar();
    Foo f = b;
    System.out.println(b.x); // prints 0
    System.out.println(f.x); // prints 1
}

あなたの例では、異なるものを含む「同じ」名前の2つのリストをクラスに入れたくありません。ただし、解決策は簡単です。基本クラスのメンバーを保護し (そうしないと、同じパッケージ内でのみサブクラス化できます)、子クラスの宣言を削除します。

コンストラクターの問題について: これは単純ですが、2 つの部分があります。コンストラクターで呼び出しを明示的に記述しない場合super、コンパイラーは自動的にsuper()呼び出しをコードに挿入します。さらに、独自のコンストラクターを作成しない場合、コンパイラーはパラメーターのないコンストラクターを生成するとすぐに、そのようなコンストラクターは自動的に生成されません。Base クラスには int を取るコンストラクターがあるため、明示的なスーパー コールを記述しないと、コンパイラsuper()は存在しない呼び出しを生成します。

基本クラスにパラメーターなしのコンストラクターを記述すると、コードはコンパイルされ、これを暗黙的に呼び出します。ただし、ユーザーが必要とするサイズを基本クラスに知らせたいので、これは悪い考えです。ここで本当に必要なのは call super(size)!

于 2013-05-27T21:24:17.467 に答える
1

別のコンストラクターを呼び出すように指示されている場合は、別のコンストラクターを呼び出してみてください。

public Sub (int size) {
   super(size); // invoke superclass constructor
   adj = new ArrayList<Collection<E>>(size);
   for(int i = 0; i < size; i++)
   adj.add(new HashSet<E>());
}

はい、これが理想的な解決策ではないことは承知しています。時間があるときにこれを修正します。

于 2013-05-27T20:27:34.030 に答える
0

これが、Java がオブジェクトを構築する方法です。サブクラスのコンストラクターが最初に行うこと (いくつかの静的初期化の後) は、スーパークラスを構築することです。Java は、スーパークラスのデフォルト コンストラクターを呼び出すことによって、これを自動的に行います。デフォルトのコンストラクターは、常に引数のないコンストラクターです。したがって、あなたの場合、これは次のようになります。

public Base() {
  // do construction work here
} 

スーパークラスにはデフォルトのコンストラクターがないため、Java はスーパークラスの構築に使用するコンストラクターを認識しません。

したがって、次のように、特殊なコンストラクターを呼び出すデフォルトのコンストラクターを追加するかのいずれかです。

public Base () {
  this(4); // default value for example
}

public Base (int size) {
   adj = new ArrayList<Collection<E>>(size);
   for(int i = 0; i < size; i++)
     adj.add(new ArrayList<E>());
}

または、@Zong li が言うように、super(size)特殊なコンストラクター内からコンストラクターを明示的に呼び出します。この場合、コンストラクターを完全にオーバーライドしたいので、空の引数なし (デフォルト) コンストラクターを選択します。

于 2013-05-27T21:05:02.227 に答える