2017-01-10 7 views
2

何らかの理由で、私が暗黙のうちにsuper()を呼びたくないと仮定します。これはデフォルトで行われます。Javaでのsuper()のデフォルト呼び出しを避けることができますか?

class Animal { 
    public Animal() { 
     System.out.println("Constructing an animal."); 
    } 
} 
class Dog extends Animal { 
    public Dog() { 
     System.out.println("Constructing a dog."); 
    } 
    public static void main(String[] a) { 
     new Dog(); 
    } 
} 

新しい犬を作るときsuper()が呼び出されることをデフォルトの動作を「無効」にする方法はありますか?あるいは、それは主に概念的に間違っていますか?

つまり、サブクラスのコンストラクタだけを必要とし、ベースクラスの構築を呼び出さずにベースクラスを継承する場合があります。

+6

唯一の方法は、 'public Animal(String name)'コンストラクタがある場合は、別の既存のスーパーコンストラクタ、たとえば 'super(" Rex ");を呼び出すことです。 – Berger

+1

この例では問題が明らかです。しかし、それは不可能なように思われるので、別の方法で見つけることができます。なぜあなたはsuper()への呼び出しをしたくないのですか? – bracco23

答えて

6

あなたが正しく理解している場合は、Animalコンストラクタの動作をオーバーライドするか、それを呼び出さないでください。もしあなたが概念的に間違っているなら、あなたは常にスーパーコンストラクタを呼び出す必要があります。コールで唯一できることは、デフォルト以外のコンストラクタ、つまり引数を持つコンストラクタを提供し、そのコンストラクタの動作に影響を与える適切な引数を提供することですたとえば、別のコンストラクタを選択したり、何らかの戦略/関数オブジェクトなどを渡したりして)

もう1つの方法は、デフォルトのコンストラクタが呼び出しているメソッドで、オーバーライドできますがいくつか問題があります。たとえば、:

  • オーバーライドされたメソッドがサブクラス(たとえば追加のフィールド)にしか見えないものにアクセスしようとすると、問題が発生する可能性がありますまだ初期化されていないものです。
  • このメソッドは最終フィールドを初期化できません。
3

親クラスの構築をバイパスすることはできません。がこのルールを迂回しようとするべきではありません。

protected Animal(Noop foo) 
{ 
    /*do nothing explicit here*/ 
} 

をそして、その1を呼び出す:あなたは必見、あなたがAnimalでno-opのコンストラクタを構築することができ、これを行う場合

しかし、(あなたがprotectedとしてマークするように唯一の派生クラスは、それを見ることができます)ここで明示的に

super(new Noop())

を使用して、派生クラスからの私は、「何の図動作を意味していない新しいクラスNoopを(発明しましたn ")、コンパイラーがコンストラクター・パラメーターを区別できるようにします。

+0

ちょっと残酷に見えます...なぜヌルか単純なブールフラグを渡さないのですか? – shmosel

+1

@shmosel:そうすることで、将来の建設方法のつま先を踏みにじる危険性があります。 – Bathsheba

+0

特別な動作を伝えるためにnoopでうまく動作します。元の問題はデザインから来ていると私は思っています。 – davidxxx

5

新しい犬を作るときにsuper()が呼び出されるデフォルトの動作を無効にする方法はありますか?または、それは主に、 は概念的に間違っていますか?スーパーコンストラクタはそれではない持っている場合は任意の引数を指定してsuper()またはsuper()

そのコンストラクタを呼び出し、任意のクラスは、その親のコンストラクタを呼び出す必要があるため、概念的に間違っています。

スーパークラスのコンストラクタが特定の処理を行い、すべての具象クラスにとって望ましくない場合は、スーパーコンストラクタの実装を変更し、スーパークラスのメソッドで特定の動作を移動するか、具体的なクラスのメソッド。

+1

プラス「概念的に間違っている」。 – Bathsheba

2

コンストラクタが直接呼び出されたときに実行され、サブクラスコンストラクタが呼び出されていないときにのみ実行されるコンストラクタ内のコードブロックを保証するもう1つの回避策を提供します。あなたが相続鎖に悪いデザインの決定の闘争を避けることができるように

public interface Animal { 
    // define behaviour 
} 

public class Dog implements Animal { 
    // implement behaviour 
} 

使用インタフェースと集約/装飾:理由の継承の一つだ

public class Animal{ 
    public Animal() { 
     if(this.getClass() == Animal.class){ 
      System.out.println("Animal"); 
     } 
    } 
} 

public class Dog extends Animal{ 
    public Dog() { 
     System.out.println("Dog"); 
    } 
} 
+0

オリジナルの問題はデザインから来ているとは思うが、ちょっとしたコードでうまく作業を進めることができます。 – davidxxx

0

は、疼痛および通常誤用です。

関連する問題