2011-12-06 14 views
0

スーパーコンストラクタで抽象メソッド呼び出しがあります。私は "コンストラクタの呼び出しがコンストラクタの最初の文でなければならない"というエラーに遭遇します。スーパーのコンストラクタを呼び出す前に、サブクラス内のいくつかの状態を初期化する必要があるからです。スーパークラスコンストラクタで抽象メソッドを呼び出す

私は、コンストラクタの呼び出しが最初でなければならないことを理解します。しかし、私にはいくつかの問題があります。

スーパークラスには、すべてのサブクラスが抽象メソッドを実装しています。 しかし、サブクラスのコンストラクタには、抽象メソッドを実行する前に処理する必要がある引数が必要です。私のコードで

は、私は、スーパークラスのコンストラクタで抽象メソッドを持っているので、あなたはもちろんの問題を理解します: スーパークラスが行います。

  1. INFO1取得し、info2にスーパー(I1、I2)を使用して
  2. は、サブクラス

を通じて抽象メソッドを実行しますが、少しのスーパークラスのコンストラクタは)それも スーパー(の下の行に宣言されている情報3と情報4を、必要なことを知っていた - ライン。

私は、スーパークラスのコンストラクタが戻って、サブクラスから情報を集める前に、 メソッドを実行する前に、何も考えていないと思っていました。

また、すべてのサブクラスの抽象メソッドで引数が異なるため、このメソッドは引数を必要としません。

経験豊富な方、どうすればこの問題を回避できますか?いくつかのグーグル後

、これをしなければならないようだ。 http://webcache.googleusercontent.co...s-constructor/

しかし、まだ初心者なので、それはハードにハングアップするために見つける... 私はこのすべてを避けていたかもしれないと感じサブクラスのコンストラクタが処理された後にsuper()を使用するだけで問題が発生する場合があります。

リクエストに応じてコード:

abstract public class Prylar { 
     abstract public Integer value(); 

     private String itemName; 
     private Person owner; 


     public Prylar(Person thisOwner, String iN){ 
     owner = thisOwner; 
     itemName = iN; 
      value = value(); 
} 



    public class Smycken extends Prylar{ 
    private int antalStenar; 
    private boolean guldEllerSilver; 
    private int value; 

    public Smycken (Person who, String n, int aS, boolean material){ 
    super(who,n); 

    antalStenar = aS; 
    guldEllerSilver = material; 
} 




public Integer value() { 

    if (guldEllerSilver){ 
     value = 2000; 
    } 
    else{ 
     value= 700;} 
    value += (500*antalStenar); 

    return value; 
} 

}

そして、私はちょうど言って、これを終了するには、読んで男を助けるためにあなたの時間を割いてありがとうございました。ほんとうにありがとう。うまくいけば、他の人が同様の問題を抱えていると、彼らはこれにつまずくでしょう。

ありがとうございました!

+4

私はあなたが私は2つのオプションを考えることができ、あなたのコード –

+0

を投稿する必要があると思う は、この例で考えてみましょう内部では明示的に外部を呼び出します。 2.追加の情報を取得し、抽象メソッドの前に呼び出す別の抽象メソッドを作成します。 btw、どうしてあなたのメソッドのシグネチャを変更できないのですか? – aishwarya

+0

コンストラクタでvalue()を呼び出してその結果を無視する理由を理解できません。私はtypoがあり、実際のコードはthis.value = value()であると推測しています。 ??? – user949300

答えて

2

問題は、ベースクラスから抽象メソッド(またはオーバーライドされたメソッド)を呼び出すときにサブクラスインスタンスが完全に構築されないことです。オブジェクトインスタンスが完全に構築されたことを確認する唯一の方法は、コンストラクタを完成させることです。

問題を解決する1つの方法は、インスタンスの構築にのみコンストラクタを使用し、メソッドに(動的な)初期化を残すことです。このようなケースでは次のようなメソッドを使用することができます。

private boolean initialized = false; 

public synchronized boolean init() { 
    if (!initialized) { 
     // allocate resources, call abstract method(s) 
     initialized = true; 
    } 
    return initialized; 
} 

public synchronized void cleanup() { 
    if (initialized) { 
     // free resources, call abstract method(s) 
     initialized = false; 
    } 
} 

のようなパターンにinit()への呼び出しを明示的にinit()cleanup()メソッドを呼び出すか、残すことができ、コードを呼び出す:あなたのinitメソッド内

public void doSomething() { 

    if (init()) { 
     // go! 
    } 
} 

抽象メソッドを呼び出して、完全なオブジェクトインスタンスが正しく構築されていることを確認することができます。

+0

つまり、コンストラクタに抽象メソッドを持たせる代わりに、別のメソッド、つまり、あなたが示唆したように初期化メソッドに入れます。 初期設定を確認するにはどうすればよいですか?あるいは、私はどのように初期化するでしょうか? –

+0

@Dennis、はい、それは私が意味するものです。コンストラクタからの抽象メソッドの呼び出しがインスタンスの初期化であると仮定すると、新しいインスタンスを作成した直後にinitメソッドを直接呼び出すことも、オブジェクトへの最初のパブリック呼び出し時に初期化を実行したままにすることもできます。 – rsp

+0

ありがとう、これは私がやったことです、それは働いているようです。 –

1

@rspで提案されている明示的なinit()メソッドの代わりに、他の結果を遅く計算することもできます。例えば

public int getValue() { 
    if (value == 0) { // some constant or value that means not-computed yet 
     value = blah*foo*bar; 
    } 
    return value; 
} 

また、value()の計算に時間がかかります。ちょうど常にそれを再計算してください。 30年前、あなたはこのすべてのものをキャッシュしていました。キャッシングは、オブジェクトがヌルまたは古くなったバグを作成します。またはサブクラス。 :-)プロセッサは今や高速ですが、しばしば再計算するほうが簡単で、時には高速です。

0

送信されたコード例を見ると、抽象メソッドが基本クラスで使用されているという兆候はありません。私はそれが簡素化のためであることを願っています。さもなければ、そのメソッドを抽象として定義するのは意味がありません。

サブクラスによって計算される基本クラスの値をキャッシュするには、コンストラクタを使用しないでください。このメソッドは、サブクラスのコンストラクタがデータを渡す機会がある前に呼び出され、あなたが観察した効果を引き起こします。

代わりに、値がキャッシュされているかどうかのチェックとキャッシュしない場合のチェックを行う抽象メソッドを定義します。

public abstract class Base { 
    private final String name; 
    private BigInteger cachedValue; 

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

    public BigInteger calculate() { 
    final BigInteger one = BigInteger.ONE; 
    //do the calculation involving `value` call 
    return value().multiply(one); 
    } 

    protected abstract BigInteger doComplexCalculation(); 

    protected BigInteger value() { 
    if (cachedValue == null) { 
     this.cachedValue = doComplexCalculation(); 
    } 
    return this.cachedValue; 
    } 
} 

この場合のサブクラスの例: - 1からメソッドを呼び出してはいけない

public class SubClass extends Base { 
    private int number; 

    public SubClass(String name, int number) { 
    super(name); 
    this.number = number; 
    } 

    @Override 
    protected BigInteger doComplexCalculation() { 
    //do calculations and return a result which will be cached by the base class 
    return BigInteger.valueOf(number); 
    } 
    //The cached value can then be accessed by other methods 
    //through the use of protected `value` method call. 
} 
関連する問題