2011-01-26 9 views
1

Javaで問題が発生しています。私は拡張できる方法があります。問題は、このメソッドがクラスの他のメソッドを呼び出すことで、これらも拡張できます。私は、次の手順を実行するとJavaで特定のクラスメソッドを呼び出す(ポリモーフィズムなし)

public class Abc extends Foo { 
} 

:このクラスでも

public class Bar extends Foo { 
    protected int xAverage = 0; 
    protected int xCount = 0; 
    protected int y; 

    public updateMe(int x, int y) { 
     super.updateMe(x, y);  
     updateX(x); 
     updateY(x); 
    } 

    protected updateX(int x) { 
     this.xAverage = (this.xAverage * this.xCount) + x; 
     this.xCount++; 
     this.xAverage /= xCount; 
    } 

    protected updateY(int y) { 
     this.y = y; 
    } 
} 

そして:このクラスは以下のクラスによって拡張され

public class Foo { 
    protected int xLast; 

    public updateMe(int x, int y) { 
     updateX(x); 
    } 

    protected updateX(int x) { 
     this.xLast = x; 
    } 
} 

は、次のクラスを考えてみましょう:

Foo myBar = new Bar(); 
myBar.updateMe(1, 2); 

Foo.updateXメソッドは呼び出されませんが、Bar.updateXメソッドは2回呼び出されます。いくつかのソリューションは、いくつかは、うまく動作したり、非常に醜いはありません、ありますBar.updateXコールsuper.updateX

  1. 。これにより、両方のupdateXメソッドが2回呼び出されます。
  2. Foo.updateMeupdateXコールを削除して、拡張クラスがsuper.updateXを呼び出すようにします。これにより、クラスAbcに不要なコードが必要になります。そうしないと、AbcクラスはupdateXを呼び出しません。
  3. メソッドが互いにオーバーライドしないようにメソッドの名前を変更します。これは機能しますが、安全ではありません(将来、これは忘れられて問題につながるかもしれません)。また、言語によって強制されません。

これは多少コード臭のことですが、これを行う方法はわかりません。

基本的に私はこのようなことをしています:Foo.updateMeFoo.updateXと具体的にはupdateXに電話したいと思います。

C#でnewメソッドキーワードのようなものが私の問題を解決できるとは思っていますが、Javaではこれを実現する方法がないようです。

編集:私はちょうど問題のあるメソッドの名前を変更することを選んだ最後に

。私はこの問題を引き起こすただ一つの方法を持っています、そして、解決策はここで示唆されました、しかし、デザインの観点からの音はこの特定のコードを理解し、維持するのをより困難にします。

+0

IOC(Inversion of control)を使用することはできますが、私は本当に理解できません。http://en.wikipedia.org/wiki/Inversion_of_control –

+1

この質問とIOCとの関係は何ですか?IOCは私たちの永遠の問題を終わらせるための銀の弾丸ではありません。 –

答えて

3

私はこれを行うだろう:

  1. updateXすでにsuper.updateMeによって呼び出されupdateX以来Bar.updateMeから()の呼び出しを()()()を外します。
  2. Bar.updateX()からsuper.updateX()を呼び出すのは、同じ名前のメソッドが機能を拡張して置き換えるのではないためです。

この場合、Abcは変更する必要はなく、両方のupdateX()メソッドは一度呼び出されます。

+0

私はあなたの提案が好きであり、またそれは最も論理的に正しいものです。 –

1

Javaでは、すべてのインスタンスメソッド呼び出しは動的バインディングによって呼び出されます。私が知る限り、あなたが望むものを達成するエレガントな方法はありません。

原則と優雅さを気にかけなければ、Fooのインスタンスのクラスを確認できます。

public updateMe(int x, int y) { 
    if (getClass()==Foo.class)   
     updateX(x);  
} 
+0

これは、実際には、特にすべてのケースを扱うロジックを追加するときに(拡張クラスがいくつかの 'super'メソッドを呼び出すのであって、他のメソッドを全く呼び出さないなど)、これを扱うのはむしろばかばかしい方法です。 –

+0

As私は言った、エレガントで合理的な方法はありません。 –

1

Eli、あなたはOOPをキャンセルしたいと思われます。最初は悪いです。これが必要な場合は、デザインを変更します。 Javaは純粋なオブジェクト指向言語なので、すべての呼び出しは多態的です。あなたのクラスを拡張し、その機能が必要な場合は、この機能を呼び出す必要があることを意味するいくつかのオーバーロードする場合。これが理由でupdateX()からBarが呼び出されます。

私は静的メソッドを作成し、このように呼び出す必要があります:Foo.updateX()。

+0

これは古典的なOOPではないことを認識しています。 'updateX'では非静的メンバーにアクセスする必要があるので、静的メソッドにすることはできません。 –

+0

一般に、非静的メソッドへのアクセスは問題ではありません。静的メソッドのパラメータとしてインスタンスを渡し、インスタンスのフィールドにアクセスすることができます。 – Kel

+0

@Kelはい、それはむしろ醜い解決策だと思います。 –

0

また、updateX()を非公開にすることもできます。次に、updateX()を実装するサブクラスは、メソッドを「オーバーライド」していない「隠蔽」されています。

欠点: updateX()は概念的にはテンプレートパターンの一部なので、実際には保護する必要があるように感じます。

abstract private void updateX(); をスーパークラスに入れて、強制的に実装することはできません。

updateMeのすべての実装は、()は常にupdateXを(呼び出すことを覚えておく必要があります)

可能な欠点と考えられる利点:

プライベートupdateMe()メソッドのすべてが呼び出されます。 (私にとってはこれが望まれていました、YMMV)

最近この問題に直面して、メソッドの名前を変更し、(getClass()== MyFoo.class)トリックに非常に近いものを考えました。 IMOはすべて合理的です。

関連する問題