web-dev-qa-db-ja.com

なぜコンストラクタはJavaで継承できないのですか?

私はJavaプログラミング言語の初心者です。最近、constructorsはJavaでは継承できないことを研究しました。誰か説明してくださいなぜ

私はすでに読んだ このリンク C++

37
Mayank Tiwari

簡単に言えば、サブクラスでは異なる名前(サブクラスの名前)を持っているため、コンストラクターを継承することはできません。

class A {
   A();
}

class B extends A{
   B();
}

あなただけができる:

B b = new B();  // and not new A()

代わりに、メソッドは「同じ名前」で継承され、使用できます。

理由としては、クラスAのコンストラクターはタイプAのオブジェクトを作成することを意味し、クラスBのコンストラクターはクラスBのオブジェクトを作成することを意味するため、コンストラクターを継承する意味はあまりありません。

ただし、Bの実装内のAからseコンストラクターを引き続き使用できます。

class B extends A{
   B() { super(); }
}
35
Lake

あなたが話しているのは、Java言語レベルです。コンストラクタが継承されると、クラスをプライベートにすることができなくなります。知っているように、メソッドの可視性はダウングレードできません。 Objectクラスには引数なしのコンストラクターがあり、すべてのクラスがObjectを拡張するため、コンストラクターの継承の場合、すべてのクラスに引数なしのコンストラクターがあります。これはOO原則を破ります。

バイトコードレベルでは状況が異なります。オブジェクトが作成されると、2つの演算子が呼び出されます。

  1. new -オブジェクトにメモリを割り当てます
  2. invokespecial -新しく割り当てられたメモリ上でコンストラクタを呼び出します

バイトコードを変更して、子クラスにメモリを割り当て、親クラスからコンストラクターを呼び出すことができます。この場合、コンストラクタは継承されていると言えます。バイトコード検証をオフにしないと、クラスのロード中にJVMが例外をスローします。これを行うには、-noverify引数を追加します。

結論:

  1. OO原則により、コンストラクターは言語レベルで継承されません
  2. コンストラクターはバイトコードレベルで継承されます
15
Mikhail

継承のドキュメントで言及されている理由

サブクラスは、スーパークラスからすべてのメンバー(フィールド、メソッド、ネストされたクラス)を継承します。コンストラクターはメンバーではないため、サブクラスに継承されませんが、スーパークラスのコンストラクターはサブクラスから呼び出すことができます。

クラスへのコンストラクターの提供 のドキュメントを参照できます。

12
Suresh Atta
  • コンストラクターは、newでのみ呼び出すことができます。メソッドとして呼び出すことはできません。
  • コンストラクター名はクラス名と同じです。

したがって、継承は実際には不可能です。ただし、コンストラクトでは、他のコンストラクターを呼び出す場合があります。

  • this(...);を使用した同じクラス内
  • super(...);を使用した拡張クラスの

_class A {
    A() { }          // Constructor
    A(int a) { }     // Constructor
    A(boolean c) { } // Constructor
}
class B extends A {
    B() {
        this(3, 7);
    }
    B(int a) {
        super();
    }
    B(String b) {
        super(7);
    }
    B(int a, int c) { // Calls super() implicitly
    }
}
A a = new B(8):
_

残念ながら、ブール値にAのコンストラクタを使用する可能性はありません。

_B b = new B(true): // ERROR
_

言語設計者は、次のようなものを実装できます。

基本クラス内のすべてのパブリックコンストラクターに対して、そのようなコンストラクターがまだ定義されていない場合、同じシグネチャを持つコンストラクターを生成します。同じパラメーターでsuperを呼び出します。デフォルトのコンストラクターがある場合は、this()を呼び出します。

それはコードを少し肥大化しているようです。また、メソッドの継承/オーバーライドが機能する仮想メソッドテーブルの単なるポインターではありません。

3
Joop Eggen

私が観察した簡単な答えは、子クラスで直接親クラスのコンストラクタを呼び出したり使用したりすることはできませんが、子クラスで直接使用できる親クラスのメソッドです。

その時点で親クラスと同じ名前の子クラスのメソッドがある場合、「スーパー」キーワードを使用して、親クラスのメソッドを呼び出してあいまいさを解決する必要があります。

子クラスの親クラスコンストラクターを「呼び出す」には、常に「super」キーワードが必要です。したがって、子クラスの親クラスメソッドのように、親クラスコンストラクターは「直接利用できません」ので、コンストラクターを継承できないと言えます。

2
Nikhil

コンストラクターはクラスのメンバーではなく、メンバーのみが継承されます。コンストラクターを継承することはできません。つまり、スーパークラスのいずれかのコンストラクターを使用してサブクラスのインスタンスを作成することはできません。

2
Rahul Tripathi

概念的な方法で機能に何らかの理由がある場合、構文上の制限はしばしば回避できます。これにより、コンストラクタの継承をサポートしない本当の理由は、構文上の制限によるものではなく、セマンティクスによるものだと思います。

概念的に継承は、動作を取得(または継承)するメカニズムを提供します。その目的は、コードの再利用を提供することであるため、ほとんどの場合、コードを記述することなく動作します。子クラスの場合、親クラスの初期化の動作を継承することはありません。結局のところ、継承された動作は、外部の呼び出し元が(親チェーン内の)誰が実際にそれを実装したかを知らなくても使用できる場合に、最適な使用方法を見つけます。ご覧のように、呼び出し元は、子クラスを介して親クラスがどのように初期化されるかを知っているビジネスはほとんどありません。(親クラスの)コンストラクターの継承をサポートする明確な理由はありません。

1
KGhatak

コンストラクタを継承することはできませんが、コンストラクタの初期化された値を次のように継承できます

class test1 {
    int a,b;
    test1(){
        a = 100;
        b = 20;
    }
}

class test2 extends test1 {
    test2(){
        // do something
    }
}

class test {
    public static void main(String[] args) {
        test2 t = new test2();
        int a = t.a;
        int b = t.b;
        System.out.println(a+b);
    }
}
1
J.d. Patel

ミハイルが述べたとおり。コンストラクターは継承されません。スーパークラスからサブクラスにコンストラクターを継承することはできません。ただし、Javaの「new」演算子を使用してオブジェクトをインスタンス化すると、そのオブジェクトは、抽象クラスにあるものも含めて、サブクラスからスーパークラス(親)にすべてのコンストラクターを継承します(スーパークラスでもあるため)。

1
Henry Nana Adu

いいえ、コンストラクタはサブクラスに継承されません。コンストラクタは非静的メンバーですが、コンストラクタはオブジェクト内に読み込まれないため、サブクラスに継承されませんが、オブジェクトの作成に使用されます。コンストラクタは非静的初期化子のようなものです

1
Ashwini E

フィールド、メソッド、ネストされたクラスのみが、コンストラクターではなくクラスのメンバーです。サブクラスは、そのスーパークラスから(フィールド、メソッド、ネストされたクラス)などのすべてのメンバーを継承します。コンストラクターはメンバーではないため、サブクラスに継承されませんが、スーパークラスのコンストラクターはサブクラスから呼び出すことができます。

1
user6521421