2012-02-13 15 views
0

に基づいてスーパータイプのメンバーを初期化します。は、私は次のような状況を持っている亜型情報

 public abstract class A { 
      private Object superMember; 
      public A() { 
       superMember = initializeSuperMember(); 
       // some additional checks and stuff based on the initialization of superMember (***) 
      } 

      protected abstract Object initializeSuperMember(); 
     } 

     class B extends A { 
      private Object subMember; 
      public B(Object subMember) { 
       super(); 
       subMember = subMember; 
      } 

      protected Object initializeSuperMember() { 
       // doesn't matter what method is called on subMember, just that there is an access on it 
       return subMember.get(); // => NPE 
      } 
     } 

問題は、私は新しいオブジェクトBの作成上のNPEを得ることです。
サブクラスのコンストラクタでsubMemberコンテンツを割り当てた後でinitializeSuperMember()を呼び出すことでこれを回避できますが、サブクラスごとにこれを行う必要があることを意味します(*)。
そして、スーパークラスのコンストラクタでsuper()を呼び出す必要があるので、super()の呼び出しの前にsubMemberを初期化することはできません。私はalltogether間違って何かをしようとしていた場合

誰でもケアこれを行うには良い方法があるなら、私に教えたりするには?

答えて

2

2つの問題:

まず、あなたが発見しただけの理由で、コンストラクタからoverrideableメンバ関数を呼び出してはなりません。代わりのアプローチを含めて、問題の良い議論については、this threadを参照してください。

第二には、Bのコンストラクタでは、次のものが必要です。

this.subMember = subMember; 

コンストラクタのパラメータ名マスクフィールド名を、あなたはフィールドを参照するthis.を必要とするようにします。

+0

は、それでは、唯一の解決策は、すべてのサブクラスでは、いくつかの重複したコードを持っているのですか? – Deelazee

+0

他のスレッドへの参照ありがとう。 – Deelazee

+0

@Deelazee - それは唯一の解決策ではありません。私が参照したスレッドで説明したように、[Builderパターン](http://en.wikipedia.org/wiki/Builder_pattern)を使用することができます。密接に関連している[ファクトリメソッドパターン](http://en.wikipedia.org/wiki/Factory_pattern)を使用することもできます。 –

0

は、呼び出しの連鎖に従ってください:

  1. あなたはB()コンストラクタを呼び出します。
  2. A()コンストラクタを呼び出します。
  3. A()コンストラクタはオーバーライドされた抽象methot
  4. まだ初期化されていないsubMemberを参照B#initializeSuperMember()メソッドを呼び出します。 NPE。

あなたがやっていること行うことが有効なことはありません。

また、達成しようとしていることは明確ではありません。あなたの目標が何であるかを説明する別の質問をする必要があります。

0

問題はsuper()を呼び出すときにsubMemberがまだ初期化されていないことです。あなたはパラメータとしてsubMemeberを渡す必要があります。

public abstract class A { 
    public A (Object subMember) { 
     // initialize here 
    } 
} 


class B extends A { 
    public B (Object subMember) { 
     super(subMember); 
     // do your other things 
    } 
} 

抽象クラスでsubMemberを使用したくないので、もう1つの方法はゲッターをオーバーライドすることです。

public abstract class A { 
    public abstract Object getSuperMember(); 
    protected void checkSuperMember() { 
     // check if the supberMember is fine 
    } 
} 

public class B extends A { 
    private Object subMember; 
    public B(Object subMember) { 
     super(); 
     this.subMember = subMember; 
     checkSuperMemeber(); 
    } 

    @Override 
    public Object getSuperMember() { 
     return subMember.get(); 
    } 
} 

このコードでも重複コードが削除されることを願っています。

+1

正確なポイントは私がスーパークラスのsubMemberを望んでいないことです:) – Deelazee

0

ハムは、このコードはよく見えず、すべての可能性が高いですが、これは悪い状況の兆候です。しかし、あなたはこのようにファクトリメソッドを使用して、あなたがやりたいことを助けることができるいくつかのトリックがあります。

public static abstract class A { 
    public abstract Object createObject(); 
} 

public static abstract class B extends A { 
    private Object member; 

    public B(Object member) { 
     super(); 
     this.member = member; 
    } 

} 

public static B createB(final Object member) { 
    return new B(member) { 

     @Override 
     public Object createObject() { 
      return member.getClass(); 
     } 
    }; 
} 
関連する問題