【问题标题】:F# interfaces and propertiesF# 接口和属性
【发布时间】:2015-08-05 07:04:53
【问题描述】:

我正在尝试掌握 F#,并且在此过程中我正在转换一些 C# 代码。我在定义接口中的属性并在类型中实现它们时遇到了一些麻烦。

考虑以下代码:

module File1

type IMyInterface =
    abstract member MyProp : bool with get, set
    abstract member MyMethod : unit -> unit

type MyType() = 
    interface IMyInterface with
        member val MyProp = true with get, set
        member self.MyMethod() = if MyProp then () else ()

The documentation for F# properties 似乎表明我在 MyType 中的 MyProp 实现是正确的,但是,编译器抱怨“未定义值或构造函数 'MyProp'”。有什么想法吗?

【问题讨论】:

  • 试试self.MyProp - 你需要this 限定符;)
  • @Carsten 似乎不适用于自动属性

标签: interface f# automatic-properties


【解决方案1】:

要访问(显式)接口中的属性,您需要强制转换为对接口类型的self 引用:

type MyType() = 
    interface IMyInterface with
        member val MyProp = true with get, set
        member self.MyMethod() = if (self :> IMyInterface).MyProp then () else ()

如果显式实现接口,在 C# 中也会出现相同的错误,并且还需要强制转换才能访问成员:

interface IMyInterface
{
    bool MyProp { get; set; }
    void MyMethod();
}

class MyType : IMyInterface
{
    bool IMyInterface.MyProp { get; set; }

    void IMyInterface.MyMethod()
    {
        if (((IMyInterface)this).MyProp) { }
    }
}

【讨论】:

  • 啊哈!我不知道这实际上是一个显式的接口实现。有没有办法隐式实现它?
  • 据我所知,在 F# 中所有接口都必须显式实现。斯科特在这里很好地解释了fsharpforfunandprofit.com/posts/interfaces
  • 没问题,在F#接口中yes只能显式实现
【解决方案2】:

如果你只是访问接口,那么你不需要在类型本身中定义成员。 如果您想要极简主义,菲尔的回答很好,但另一种方法 我喜欢使用“let-bound”值而不是成员——对于更复杂的代码,类型推断更好 他们通常比成员更容易处理。

type MyType() = 
    let mutable myProp = true 
    let myMethod() = if myProp then () else ()

    interface IMyInterface with
        member __.MyProp with get() = myProp and set v = myProp <- v
        member __.MyMethod() = myMethod()

代码也比会员版本略干净,imo,因为type MyType() as self 中的self 标记 只需要访问 members -- let-bound 值可以直接从接口访问。

【讨论】:

  • 我喜欢这样想:(a) 我用 let 绑定的值和函数(相当于私有方法,比如说)做所有的实际工作,然后 (b) 我暴露了一些通过一个或多个接口实现该功能。然后,接口只是“真实”代码的代理。
【解决方案3】:

这是一个工作版本:

type IMyInterface =
    abstract member MyProp : bool with get, set
    abstract member MyMethod : unit -> unit

type MyType() = 
    member val MyProp = true with get, set
    member self.MyMethod() = if self.MyProp then () else ()
    interface IMyInterface with
        member self.MyProp with get () = self.MyProp and set v = self.MyProp <- v
        member self.MyMethod() = self.MyMethod()

请注意,我包含了明确的成员,因为您肯定会错过它们;)

【讨论】:

  • 我知道这行得通,但我想要自动属性,而不是明确的支持字段...
  • MyProp 是一个自动属性 ​​- 它只是覆盖它的接口实现 - 也许有更短的方法,但老实说,我尽量不使用可变值,所以我不确定; )
  • @Eyvind 根据我的经验,F# 在功能上使用时非常优雅,但在面向对象的方式使用时会变得“混乱”。这会激励你去寻求好的功能设计 :)
  • 它只是 messy 因为你没有得到隐式接口,所以你要么必须做某些事情两次(如这里),要么你必须做 (myType :&gt; IMyInterface).MyProp 所有时间 - 无论如何,正如 Mark 所说,如果您尝试 1:1 复制您从 C# 中知道的内容,您将不会高兴
  • @Eyvind 我认为类型推断和隐式转换之间存在差异。 F# 将为您推断类型,“就好像”您已经明确地注释了它们,但它不会隐式地将类向上转换为接口或基类(有某些例外)。它也不会隐式地将 int 转换为 float,甚至不会将 int64 转换为 int32!我认为这就是卡斯滕所说的。您可以在 C# 中做很多事情,而 F# 会抱怨并迫使您明确表达自己的意图。过了一段时间,你甚至会变得喜欢所有的抱怨!
猜你喜欢
  • 2013-02-04
  • 2012-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-31
  • 2010-09-20
  • 1970-01-01
相关资源
最近更新 更多