25

Javaの継承について質問です。

私は2つのクラスを持ってAおりB、クラスBはAから継承しています:

public class A {
     public A() {
         System.out.println("Hi!");
     }
}


public class B extends A {
     public B() {
         System.out.println("Bye!");
     }

     public static void main(String[] args) {
         B b = new B();
     }
}

プログラム B を実行すると、出力は次のようになります。

Hi!
Bye!

質問: のコンストラクターclass A呼び出されるのはなぜclass Bですか?

私は、B が A からすべてのものを継承していることを知っています - すべてのインスタンスまたはクラス変数、およびすべてのメソッド。この意味で、B のオブジェクトは A のすべての特性に加えて、B で定義されたいくつかの他の特性を持っています。しかし、私は知りませんでしたし、知りませんでした」タイプ B のオブジェクトを作成すると、A のコンストラクターも呼び出されると想像してみてください。だから、これを書く:

B b = new B();

タイプ B とタイプ A の 2 つのオブジェクトを作成します。

これは面白くなってきました、

誰かがなぜこれが起こるのか説明できますか?

4

15 に答える 15

31

2 つのオブジェクトを作成するのではなく、1 つだけを作成します: B

別のクラスから継承する場合は、コンストラクターで super() を呼び出す必要があります。そうしないと、ご覧のとおり、コンパイラがその呼び出しを挿入します。

スーパークラス コンストラクターが呼び出されるのは、そうしないと、オブジェクトが初期化されていない状態のままになり、サブクラスの開発者にはわからない可能性があるためです。

コンパイラが super 呼び出しを挿入した後、サブクラスは実際には次のようになります。

public class B extends A {
    public B() {
        super();
        System.out.println("Bye!");
    }
}
于 2009-01-28T18:28:16.483 に答える
18

2 つのオブジェクトを作成するのではなく、B のインスタンスを 1 つだけ作成します。スーパー クラス コンストラクターが呼び出される理由は、あなたが言ったように、B には A のすべてのフィールドがあり、これらのフィールドを初期化する必要があるためです。

于 2009-01-28T18:28:10.820 に答える
6

継承は、基本クラスとサブクラスの間の「is a」関係であることを忘れないでください。したがって、サブクラスのインスタンスを作成するたびに、定義により、基本クラスのインスタンスも作成されます (2 つのインスタンスとしてではなく、インスタンスの一部として)。個別のインスタンス)。基本クラスを適切に初期化するために、コンストラクターが呼び出されます。

さらに、基本クラスの内部状態に依存するサブクラスを作成するとどうなるかを考えてみてください。その場合、基本クラスのインスタンスを初期化したくありませんか?

于 2009-01-28T18:27:38.417 に答える
3

これは、コンストラクターを使用してオブジェクトを初期化するために行われます。B も A であるため、最初に A のコンストラクターを呼び出し、次に B のコンストラクターを呼び出します。

補足として、super(arg1, etc)渡すパラメーターの型に基づいて呼び出される A のコンストラクターを選択するために使用できますが、コンストラクターの最初の行である必要があります。

于 2009-01-28T18:30:00.240 に答える
2

コンストラクターには、A のすべての初期化が含まれています。2 つのオブジェクトを作成していません。1 つのオブジェクトを作成し、スーパークラスの初期化子を実行してそのメンバーを初期化し、派生クラスの初期化子を実行してそのメンバーを初期化します。

于 2009-01-28T18:28:36.090 に答える
2

2 つのオブジェクトを作成するのではなく、1 つのオブジェクトを作成するだけです。b はタイプ B で、タイプ A です。コンストラクターは基本的に、ここで私を構築するために必要なことを言っています。したがって、新しい「B」インスタンスを作成するときは、B() と A() の両方であるオブジェクトを作成しています。次のシナリオを想像してください。

class Q {
  int i;
  public Q() {
    // set default value
    i= 99;
  }
}

class Z extends Q {
  public Z() {
  }
}

Q のコンストラクターが呼び出されなかった場合、どのようにデフォルト値を取得しますか?

于 2009-01-28T18:29:36.480 に答える
2

B を作成しても、追加の A は作成されません。

しかし、B を作成することで、一種の A を作成します。BAであるためです。

Java/C++ は、暗黙的に A のコンストラクターを呼び出します。なんで?言語設計。ただし、 A のコンストラクターにはいくつかの初期化が含まれている可能性があるため、そうしても問題ありません。B は A のすべての機能とバグを使用するため、これらの機能は適切に初期化する必要があります。

于 2009-01-28T18:30:49.207 に答える
2

クラスのコンストラクターは、ほとんどの OOP で非常に重要な概念です。

クラスは、状態とその状態を操作する手段を提供することにより、不変条件の保守を容易にします。コンストラクターの役割は、クラスをこれらの不変条件に準拠する状態にすることです (またはスローして、invliad オブジェクトの使用を禁止します)。コンストラクターは独自の「this」参照を他の場所に渡すことが許可されているため、これは多くの言語で意図されているよりもやや緩いですが、これは少なくともクラスの制御下にあります (そのため、十分に安定した有効な状態にあることを知ることができます)。世界中の人がアクセスできるようにするため)

B は非常に現実的な意味での A であり、したがって、A によって提供される任意のメソッドを呼び出すことができるため、継承によってこれが複雑になります。したがって、A である B の部分は、B が調べる前に自分自身を初期化する機会を得る必要があります。 A のコンストラクターは、B コンストラクターの実際の作業が始まる前に呼び出されます。

于 2009-01-28T18:31:02.123 に答える
1

新しいオブジェクトが create(B) の場合、内部に BA オブジェクトが作成されます ( extends キーワードのため) 。B クラス JVM では B クラス コンストラクターを検索しますが、 extends キーワードにより、スーパー クラス コンストラクターに移動します。内部 クラス x 値が初期化されます。getXxx()ただし、x はプライベートであるため、クラス外の throwメソッドにアクセスして結果を取得できます 。

于 2012-10-05T12:15:29.393 に答える
1

A がそのコンストラクターでメンバーを初期化し、派生クラスで super を呼び出すのを忘れた場合、A のメンバーは悪い状態になる可能性があります。Java は、あなたが自分の足を撃たないようにしようとしています。

于 2009-01-28T18:28:31.927 に答える
1

1 つのオブジェクトのみが作成され、両方の請負業者が同じオブジェクトで実行されます。

B には A のすべての変数とメソッドがあることがわかっているため、A のメソッドが機能するように A の変数を初期化する必要がある場合、誰かがそれを初期化する必要があります。その誰かが A のコンストラクタです。

例えば:

public class A {
     public A() {
        x = 1;
     }
     private int x;
     public int getX() {
        return x;
     }
}


public class B extends A {
     public B() {
     }

     public static void main(String[] args) {
         B b = new B();
         System.out.println(b.getX()); // should print 1 
     }
}
于 2009-01-28T18:29:46.027 に答える
0

Javaでは、子クラスのオブジェクトを作成すると、オブジェクトクラスはすべてのスーパークラスの親であり、オブジェクトクラスのコンストラクターを呼び出すと、オブジェクトのみが作成され、Javaは多重継承をサポートしないため、親クラスのコンストラクターが常に呼び出されますクラスの場合、他のクラスを拡張する場合、子クラスと Object クラスの間の関係は Parent クラスを介して行われるため、Object クラスのコンストラクターを呼び出すには、Parent クラスのコンストラクターを呼び出す必要があります。

于 2015-06-27T11:45:56.913 に答える
0

すべてのスーパークラスにはコンストラクターがあり、サブクラスのオブジェクトが作成されるときに、階層の各コンストラクターが実行されます。

于 2018-08-05T08:56:05.663 に答える
-3

スーパークラスオブジェクトが作成されていない場合、サブクラスがスーパークラスの非静的メソッドと変数にアクセスする方法。

非静的メソッドと変数は、オブジェクトを介してのみアクセスできることを調べました..

于 2015-06-28T12:13:16.093 に答える