在F#中实现一个C#接口

3

我在C#中有以下接口:

public interface IDog
{
    String Bark();
}

我希望用F#创建一个实现。这个没有问题:

type GermanShepherd() = 
        interface IDog with
            member this.Bark() = "Woof"

但是当我添加了一个不属于接口的支持函数,就像这样:
type GermanShepherd() = 
        interface IDog with
            member this.Bark() = "Woof"
            member this.Eat() = "Yummy" 

编译器报错:
Error   1   No abstract or interface member was found that corresponds to this override 
Error   2   This value is not a function and cannot be applied*

有没有一种方法可以在实现接口的类型中实现私有/内部函数,而这些函数不是接口的一部分?我无法更改我的“真实”应用程序中的接口,因为有其他项目实现了该接口。我在 MSDN 上找到的所有示例都没有这种特殊情况。
1个回答

10

interface块应该只包含作为接口的一部分的函数,但你可以在块之前放置其他函数:

interface 块只包含接口的函数,其他函数应该在块之前定义:

type GermanShepherd() = 
    member this.Eat() = "Yummy" 
    interface IDog with
        member this.Bark() = "Woof"

如果您不需要公共成员,那么可以使用私有的let绑定函数:

type GermanShepherd() = 
    let eat() = "Yummy" 
    interface IDog with
        member this.Bark() = "Woof"

需要注意的是,F#目前仅允许显式接口实现,这意味着您可以将GermanShepherd视为IDog,但您不会显式地看到IDog成员:

let g = GermanShepherd()
g.Eat()            // OK
g.Bark()           // Error, interface members are implemented explicitly
let d = g :> IDog  // To 'Bark', we need to get 'IDog' first
d.Bark()           // OK

一个解决方法是将Bark方法明确地作为单独的成员添加到interface块之外。虽然这也存在F#语言问题


这个可以用,我会使用它。但是我注意到它违反了“向下规则”,即私有/支持函数应该放在公共函数之下。谢谢! - Jamie Dixon
你也可以在接口块后面放置成员,但是对于私有的let绑定来说并非如此。 - Tomas Petricek
@JamieDixon 在 F# 中,私有/支持函数几乎总是在公共函数之前 - 如果它们是 let-bound 函数,则必须如此。由于 F# 编译器严格按照自上而下的顺序工作,因此无法真正将 step-down 规则应用于 F# 代码。 - Joel Mueller
1
谢谢。当我使用F#时,我真的必须强迫自己忘记C#的习惯用法。 - Jamie Dixon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接