2011-10-25 11 views
6

は、私はJavaで、次の例のクラスを持っている:スーパータイプのコンストラクタを直接呼び出すことはできません - なぜそうではありませんか?

public class A { } 

public class Super { 
    protected Super() { } 
    public Super(A a) { } 
} 

public class Sub extends Super { } 

public class Consumer { 
    public Consumer() { 
     Sub sub = new Sub(new A()); //compiler error 
    } 
} 

コンパイラエラーが引数が完全に理解できるサブにおけるデフォルトコンストラクタに適用することはできないと述べています。私は好奇心だ何

は、この決定の根拠です。 JavaはSubにデフォルトの空のコンストラクタを生成します。なぜこの場面の裏でそれを呼ぶことができないのですか?これは主に純粋な手持ちのケースですか、技術的な理由がありますか?私は、これは言語の制限ですことを承知している

EDIT

。私は興味がありますなぜそれは言語の制限です。

EDIT 2

しばしばそうであるように、私は私が実際に大きな画像を見ることがで働いていたコードに近づきすぎた、ということらしいです。私はこれがBadThing®である理由を示す以下の回答に反例を掲示しました。

+0

私が仕様で見つけることができたのは、それができないということでした。理由についての説明はありませんhttp://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.2 –

+1

ここにJon Skeetが取り上げています。http://stackoverflow.com/questions/1644317/java -constructor-inheritance/1644410#1644410 –

+1

あなたの編集について混乱します。 1つの引数でコンストラクタを呼び出すと、引数のないデフォルトのコンストラクタをその場所で呼び出すことができないのはなぜでしょうか?明らかに、プログラマーは自分のパラメーターを完全に無視するコンストラクターを呼び出そうとしていませんでした。そうでなければ、パラメーターを指定しませんでした。 –

答えて

2

私はそれが両方readibilityの問題だと思うと意図を想定していません。あなたは言う

Javaは、デフォルトの空のコンストラクタを生成します。なぜこの場面の裏でそれを呼ぶことができないのですか?Aを無視し、Super()コンストラクタを呼び出すことよりも、Javaは暗黙的に「舞台裏」Super(A)コンストラクタを呼び出すようにするために

しかし私には、それははるかに理にかなって。

あなたが持っています。この場合、(またはの可能性があります)何が起こるべきかについて、すでに2つの異なる仮定があります。

Java言語の基本原則の1つは、透明性です。できるだけ多くの場合、プログラマは何が起こるのかをコードで見ることができるはずです。時には便宜上、というマジックを構文レベルで犠牲にしてください。

プログラマの意図があいまいであると思われる場合、Java言語は、何らかの(任意のまたはその他の)選択アルゴリズムによってデフォルトを自動的に選択するのではなく、コンパイルエラーを優先することがあります。

+0

良い点が、私の声明を誤解しているようです。私はそれをもっと明確にするためにそれを更新します。それはあなたの議論を変更することはできません... – arootbeer

2
public class Sub extends Super { } 

は、コンストラクタSub(A a)を持たず、デフォルトのコンストラクタSub()のみを持ちます。

コンストラクタは継承されません。

+0

コンストラクタは継承されているため動作しません。 – mikek3332002

+0

@ mikek3332002:スーパークラスのコンストラクタはサブクラスからのみ呼び出せますが、継承されていないと思います。 –

0

デフォルトのパブリックコンストラクタをがオーバーライドしましたので、コールするものはありません。

だからクラスのSubは

public class Sub extends Super 
{ 
    protected Sub(){} 
    public Sub(A a) { } 
} 

と同等であることになるのでその

  • まともな行動 - プログラマによって指定され、それはまた、OOP言語
  • の中の継承の概念を次のように動作します
  • C++レガシーに続いて
2

基本クラスにはオブジェクトが適切にインスタンス化されることを保証するためにスーパーコンストラクタを呼び出します。たとえば、考えてみます。

class Super { 
    final String field1; 

    public Super(String field1) { 
     this.field1 = field1; 
    } 
    ... 
} 


class Base extends Super { 
    final String field2; 

    public Base(String field2) { 
     this.field2 = field2; 
    } 
    ... 
} 

BaseのコンストラクタはSuperコンストラクタをオーバーライドしますか?その場合、field1はもはや初期化されることが保証されなくなり、継承されたメソッドは予期せずに動作します。あなたはサブクラスにデフォルト以外のコンストラクタを追加

瞬間は、コンストラクタは動作を停止継承されました。技術的には不可能ではない理由は見当たりませんが、それは言語に追加された機能が混乱してめったに役に立たないと思います。

+0

このカウンタ例の問題は、デフォルトのコンストラクタを伴わないことです。あなたはこのコードが問題であることは間違いありません。それもコンパイルされませんでした。しかし、私の質問は、特にデフォルトコンストラクタの周りです。 – arootbeer

+0

Subはコンストラクタを持たないため、このような場合にのみコンストラクタが継承されていれば混乱します。 –

+0

私の例は 'Sub'にコンストラクタがないので問題になります。私はそれが混乱するだろうとあなたに同意するでしょうが、この質問は、なぜそれが混乱するのかを正確に見つけようとすることです。 – arootbeer

0

私はこれをこの動作の技術的理由として挙げています。私はこれが意味論的に混乱するかもしれないといういくつかの他の答えと一致しています。

以下の例を考えてみますSubが構築されるとそれは言語魔法なので、この場合にSub上のデフォルトコンストラクタは、どのSuper上のデフォルトコンストラクタのだろうが、チェーン(と呼ばれることになる、

public class A { } 

public abstract class Super { 
    protected Super() { 
     // perform time consuming, destructive, or 
     // otherwise one-time operations 
    } 

    public Super(A a) { 
     this(); 
     // perform A-related construction operations 
    } 
} 

public class Sub extends Super { } 

public class Consumer { 
    public Consumer() { 
     Sub sub = new Sub(new A()); 
    } 
} 

を定義する)。次に、Super(A)への呼び出しは、構築時に一度実行されるように設計されたロジックを呼び出します。これは明らかに開発者が意図するものではありません。

this()コンストラクタでの呼び出しがなくても、開発者の意図を判断することはできません。コンストラクタは何らかの理由で互いに排他的であってもよい。

関連する問題