2

私は魔法の前半の部分を知っていました。私が持っていると仮定します:

public class Foo {}
public class static FooExt
{
    public static void M(this Foo f) {}
}

コンパイラを呼び出すfoo.M()と、コンパイラがに変更されFooExt.M(foo)ます。

しかし、継承はどうですか?例えば:

public class Bar : Foo {}
public class static BarExt
{
    public static void M(this Bar b) {} 
}

私が呼び出すときbar.M()、それは呼び出すFooExt.M()BarExt.M()?実際、私はそれをテストし、答えはですBarExtが、なぜですか?wow.M()別のものがあるWow : Fooがない場合、電話するとどうなりWowExt.M()ますか?

4

3 に答える 3

10

コンパイラーは、呼び出しサイトの引数に最も近い引数を持つ拡張メソッドを探します。タイプの変数がある場合はBarBarExt拡張子が使用されます。これBarは、より具体的なタイプであり、したがって、インスタンスFooを取得する代替メソッドよりも厳密に一致するためです。Fooこれは、あいまいなメソッドのオーバーロードが解決される方法と実際にはそれほど違いはありません。

このコードが以下を呼び出すことは注目に値しますFooExt.M()

Foo bar = new Bar();
bar.M();

これは、拡張メソッドが仮想ではないためです。メソッドを呼び出す変数はtypeFooであるためBar、拡張メソッドのバージョンは考慮されません。 拡張メソッドのバインドは、コンパイル時に完全に行われます。

あなたが示した2番目のケース(タイプの変数でextensionメソッドを呼び出すWow)では、FooExt.M()よりよく一致するものがないため、メソッドが使用されます。

于 2013-01-21T22:41:40.180 に答える
5

私はそれをテストしました、そして答えはですBarExt、しかしなぜですか?

コンパイラは、呼び出しに「最適」な拡張メソッドを選択するためです。直接取る方法があるのでBar、それを選びます。

別のWow:Fooがあり、WowExt.M()がない場合、wow.M()を呼び出すとどうなりますか?

繰り返しになりますが、使用法に「最適」な拡張機能が選択されます。をとるメソッドはありませんが、Wow親クラスをとるメソッドFooが選択されますFooExt.M()

拡張メソッドは実際には静的メソッド呼び出しの単なる構文糖衣であるため、「通常の」メソッド解決と同じルールが適用されることに注意してください。

于 2013-01-21T22:41:44.573 に答える
3

拡張メソッドを解決するときに、最も具体的なタイプの一致が選択されます。最初のケースでBarExt.M()は、が最も具体的です(BarではなくターゲットFoo)。

2番目のケースでは、Wow拡張子がないため、最も具体的な一致はですFooExt.M()

于 2013-01-21T22:42:31.427 に答える