在查看Go如何处理接口并喜欢它之后,我开始考虑如何在C#中实现类似的鸭子类型:
var mallard = new Mallard(); // doesn't implement IDuck but has the right methods
IDuck duck = DuckTyper.Adapt<Mallard,IDuck>(mallard);
DuckTyper.Adapt
方法将使用System.Reflection.Emit
动态构建适配器。也许有人已经写过这样的东西了。我想它与模拟框架已经做的并没有什么不同。
但是,如果Mallard
实际上没有正确的IDuck
方法,则会在运行时抛出异常。为了在编译时提前得到错误,我必须写一个MallardToDuckAdapter
,这正是我想要避免的。
有更好的方法吗?
编辑:显然,我称之为“安全鸭子打字”的正确术语是structural typing。
答案 0 :(得分:13)
如果你面前没有一头活生生的呼吸牛,你怎么能知道一头母牛是不是像鸭子一样嘎嘎叫而像鸭子一样呱呱叫?
Duck-typing是在运行时使用的概念。编译时的类似概念是structural typing,这是CLR不支持的AFAIK。 (CLR以nominative typing为中心。)
[结构类型系统]与主格系统形成对比,在主格系统中,比较基于显式声明或类型名称,以及鸭子类型,其中仅检查在运行时访问的结构部分的兼容性。
确保duck-typing在运行时不会抛出任何异常的常用方法是单元测试。
答案 1 :(得分:5)
答案 2 :(得分:1)
我认为还有另一种方法可能会导致编译错误。
然而,这是单元测试非常适合的。您可以编写单元测试来验证
DuckTyper.Adapt<Mallard, IDuck>(mallard);
成功制作地图。
答案 3 :(得分:1)
我知道VB 10计划了隐式接口(这就是Go接口)(不知道C#)。不幸的是,它们在发布之前被废弃了(我认为它们甚至没有进入测试版......)。很高兴看到他们是否会在未来的.NET版本中出现。
当然,新的dynamic
类型可以用来实现大致相同,但这仍然不一样 - 隐式接口仍然允许强类型,我发现这很重要。