0

誰かが私が誤解していることを指摘できますか?

次のように、AbstractとConcreteの2つのクラスがあります。

public abstract class Abstract
{
    protected static int ORDER = 1;

    public static void main (String[] args)
    {
        Concrete c = new Concrete("Hello");
    }

    public Abstract()
    {
        Class c = this.getClass();
        System.out.println(ORDER++ + ": Class = " 
            + c.getSimpleName() 
            + "; Abstract's no-arg constructor called.");
    }

    public Abstract(String arg)
    {
        this();
        Class c = this.getClass();
        System.out.println(ORDER++ + ": Class = " 
            + c.getSimpleName() 
            + "; Abstract's 1-arg constructor called.");
    }
}

public class Concrete extends Abstract
{
   public Concrete()
   {
      super();
      Class c = this.getClass();
      System.out.println(ORDER++ + ": Class = " 
          + c.getSimpleName() 
          + "; Concrete's no-arg constructor called.");
   }

   public Concrete(String arg)
   {
      super(arg);
      Class c = this.getClass();
      System.out.println(ORDER++ + ": Class = " 
          + c.getSimpleName() 
          + "; Concrete's 1-arg constructor called.");
   }
}

これを実行すると、次の出力が得られます。

1)クラス=コンクリート; Abstractの引数なしコンストラクターが呼び出されました。
2)クラス=コンクリート; Abstractの1引数コンストラクターが呼び出されました。
3)クラス=コンクリート; と呼ばれるConcreteの1引数コンストラクター。

私の質問はこれです:AbstractのString argコンストラクターからthis()を呼び出すと、Concreteでこのno-argコンストラクターが呼び出されないのはなぜですか?または、おそらくもっと適切に、AbstractのString argコンストラクターにConcreteのno-argコンストラクターを呼び出して、コンストラクターの「適切な」チェーンを可能にする方法はありますか?

4

5 に答える 5

7

いいえ-コンストラクターチェーンは常に横向き(同じタイプ)または上向き(親タイプ)になります。

呼び出しはコンパイル時に解決する必要があることを忘れないでください。呼び出しは、Abstract他のクラスがそれから派生するのか、どのコンストラクターを持つのかがわかりません。

コンストラクター内で仮想メソッドを呼び出し、そのメソッドを...内でオーバーライドすることもできますが、そうしないことをお勧めします。特に、のコンストラクター本体はまだ実行されておらず、変数初期化子も実行されていないため、特定の状態では何も実行できません。それが正しいことである非常に特殊な状況がいくつかありますが、それらはまれであり、注意して処理する必要があります。AbstractConcreteConcreteConcrete

あなたは実際に何をしようとしていますか?通常、「上向き」チェーンを持つ単一のコンストラクターにつながる多くの「横向き」チェーンを持つ方が良いと思います。

于 2009-12-07T11:55:18.043 に答える
1

それがまさにその通りです (Jon Skeet によって詳述されています)。

Concrete に init ブロックを追加することもできます:

{
  Class c = this.getClass();
  System.out.println(ORDER++ + ": Class = " 
  + c.getSimpleName() 
   + "; Concrete's init block called.");
}

デフォルトのコンストラクターとは対照的に、初期化ブロックは常に呼び出されます。

1: Class = Concrete; Abstract's no-arg constructor called.
2: Class = Concrete; Abstract's 1-arg constructor called.
3: Class = Concrete; Concrete's init block called.
4: Class = Concrete; Concrete's 1-arg constructor called.
于 2009-12-07T11:59:11.453 に答える
1

これは、抽象クラスの必要性とその仕組みに焦点を当てた投稿です。

于 2011-08-25T05:58:18.027 に答える