2016-04-27 13 views
1

Javaでのメソッド呼び出しに関しては、今日仕事中に興味深いコーナーがありました。次のことを想像して:特殊なメソッドへの呼び出しを強制します

class Bar {} 

class ExtendedBar extends Bar {} 

class Foo { 
    void doFoo(Bar bar) {} 
} 

class ExtendedFoo extends Foo { 
    void doFoo(ExtendedBar exBar) {} 
} 

今、あなたはExtendedBarのインスタンスを持っていて、ExtendedFooのインスタンスにdoFoo()を呼びたいです。私たちのテストでは、ランタイムはFoodoFoo(Bar)の実装ではなく、doFoo(ExtendedBar)からExtendedFooまでを実装しました。

もちろん、の名前を別の名前に変更するだけで済みましたが、名前を変更せずにメソッドの名前をそのまま維持することができれば、私たちを驚かせましたここでは強力な従来の文脈で使用されています。

+1

ヒント: 'doFoo(ExtendedBar)' * does not *** ***は 'doFoo(Bar)'をオーバーライドします。 * name *は実際には問題ではなく、メソッドには異なるシグネチャがあります。 –

+1

"あなたがExtendedBarのインスタンスを持っていて、ExtendedFoo_のインスタンスでdoFoo()を呼びたい場合"は 'doFoo(ExtendedBar)'を選択する必要があります。これを見てください:http://ideone.com/sJCZ3W – Hackerdarshi

+0

@Hackerdarshiええ、あなたは正しいですが、私は別の問題があったと思います(ここでは、Android ARTではネイティブJVMではなく)。 –

答えて

2

あなたは方法が、それはシェーディングをオーバーライドじゃないので、私は、まっすぐにそれを行うための方法があるとは思いません。 @Overrideを追加することで、それを簡単にアサートすることができます。

class Foo { 
    Bar doFoo() { return null; } 
} 

class ExtendedFoo extends Foo { 
    @Override 
    ExtendedBar doFoo() { return null; } 
} 

をしかし、限り、あなたはパラメータを変更すると、は、それは別の署名です:あなたは戻り値の型でこれをしなかった場合、それが正常に動作することに注意してください。

あなたがその場合にできることは、一般性を使用していると思います。

class Foo<BAR extends Bar> { 
    void doFoo(BAR bar) {} 
} 

class ExtendedFoo extends Foo<ExtendedBar> { 
    @Override 
    void doFoo(ExtendedBar exBar) {} 
} 

あなたが実際にし、適切メソッドをオーバーライドしているため、JREは適切にメソッド呼び出しを解決し、専門的なものを呼び出します。

0

他人から言われたこと以外にも、なぜここで試してみるのかは間違っています。

継承階層を定義するには、クラスに "extends Something"を入れるよりも多くのことが必要です。あなたはLiskov Substitution Principleを理解していることを確認したいと思います。あなたのケースでは

:サブクラスは、、いくつかの基本クラスで定義されたメソッドのパラメータ型のいずれかをを制限することはありません必要があります。 の戻り値の型を制限することができます(たとえば、基本クラスがNumberを返す場合はLongを返します)。 "入力"パラメータの場合、拡張できるのは、基本クラスがLongを使用する場合にNumberを許可するだけです。

適切なOOモデリングのアイデアは、Fooオブジェクトを使用しているソースコードでは、そのFooオブジェクトをExtendedFooオブジェクトで置き換えることができるはずです。あなたの提案はそのルールを破る。

+0

DIの文脈でこれほど醜い何かをすることを余儀なくされたことがないならば、私は個人的にこのようなアイデアを考え出すことはありません。私が使っているライブラリ(Dagger2)。 –

関連する問題