为什么不能投射一个实例:
sealed class Foo
{
public void Go() { }
}
Run Code Online (Sandbox Code Playgroud)
...到这个界面:
interface IBar
{
void Go();
}
Run Code Online (Sandbox Code Playgroud)
......即使Foo有签名IBar?
如何将实例Foo转换为IBar?假设我无法控制Foo.
Dai*_*Dai 25
不,C#不支持鸭子打字.
OOP解决此问题的方法是使用适配器模式.
你会这样做:
class FooBarAdapter : IBar {
private readonly Foo foo;
public FooBarAdapter(Foo foo) {
this.foo = foo;
}
public void Go() {
this.foo.Go();
}
}
Run Code Online (Sandbox Code Playgroud)
每当你有一个Foo但需要IBar你按需包装时:
public void ContrivedScenario() {
Foo foo = GetFooFromExternalDependency();
FooBarAdapter adapter = new FooBarAdapter( foo );
this.NeedsIBar( adapter );
}
public void NeedsIBar(IBar bar) { ... }
Run Code Online (Sandbox Code Playgroud)
我注意到,如果Foo至- IBar转换发生了很多,你可以使用隐式转换,所以你并不需要显式地构造FooBarAdapter的情况下,却是值得商榷的,如果这是良好的软件工程实践与否:
class FooBarAdapter : IBar {
// (same as above)
public static implicit operator FooBarAdapter(Foo foo) {
return new FooBarAdapter( foo );
}
}
Run Code Online (Sandbox Code Playgroud)
这样你可以这样做:
public void ContrivedScenario() {
Foo foo = GetFooFromExternalDependency();
this.NeedsIBar( foo ); // the conversion from `Foo foo` to `FooBarAdapter` happens implicitly
}
Run Code Online (Sandbox Code Playgroud)
C#不支持duck-typing的一个原因是因为类的接口(在OOP意义上,不是文字interface)与另一个共享相同的标识符,并不意味着它们是兼容的.例如Process.Kill(杀死过程)和MegaDeathKillBot3000.Kill(杀死所有人类)可能不应该互换使用......除非你真的想要.