F# 和接口实现的成员

Posted

技术标签:

【中文标题】F# 和接口实现的成员【英文标题】:F# and interface-implemented members 【发布时间】:2013-01-13 15:57:20 【问题描述】:

我有一个令人烦恼的错误。

type Animal =

    abstract member Name : string

type Dog (name : string) =

    interface Animal with

        member this.Name : string =
            name

let pluto = new Dog("Pluto")
let name = pluto.Name

最后一行,特别是“名称”会生成一个编译器错误,指出“未定义字段、构造函数或成员‘名称’”。

我使用的解决方法是写

let name = (pluto :> Animal).Name

但是,这很烦人,并且会产生很多视觉噪音。在 F# 中是否可以在不明确告诉编译器 Name 是 Animal 类型的派生成员的情况下解析 Name ?

【问题讨论】:

【参考方案1】:

在 F# 中,当您实现一个接口时,它相当于 explicit interface implementation in C#。即可以通过接口调用方法,但不能直接通过类调用。

F# reference article about interfaces 建议添加一个对类型进行向上转换的方法:

type Dog (name : string) =

    member this.Name = (this :> Animal).Name

    interface Animal with
        member this.Name : string = name

或者,正如 Daniel 所建议的,你可以反过来做,这意味着你可以避免这种演员:

type Dog (name : string) =

    member this.Name = name

    interface Animal with
        member this.Name : string = this.Name

此外,.Net 接口名称的约定是以I 开头,因此您的接口应称为IAnimal

【讨论】:

如果将逻辑放在类成员中并从接口实现中调用它,则可以避免强制转换。我认为这在概念上也更有意义。【参考方案2】:

另一种选择是使用abstract class 而不是接口:

[<AbstractClass>]
type Animal () =
    abstract Name : string

type Dog (name) = 
    inherit Animal()
    override dog.Name = name

let pluto = Dog("Pluto")
let name = pluto.Name

【讨论】:

以上是关于F# 和接口实现的成员的主要内容,如果未能解决你的问题,请参考以下文章

C#图解教程 第十五章 接口

接口作为成员变量——实现类和匿名内部类和匿名对象

Resharper 8 找不到接口的实现

SoapUI+excel 之REST 接口自动化

C# 显式接口成员实现

要实现foreach遍历要继承啥接口