【问题标题】:Delay the implementation of interface methods?延迟接口方法的执行?
【发布时间】:2015-07-06 14:42:41
【问题描述】:

我用 F# 编程已经有几年了,有一个“问题”一直困扰着我一段时间,我一直没能解决。这不是一个错误,我认为这是一个设计决定,但无论如何,问题是这样的:有没有办法延迟(也许这不是正确的词)接口的实现?,即不实现它们在最初的定义中,但后来,在我为该类型实现了一个模块之后,可能在同一个文件中。我将用一个简化的例子来解释: 假设我有以下数据结构:

    type 'T MyCollection =
        (*type definition*)
        interface IEnumerable<'T> with
            member this.GetEnumerator () =
                (* I don't want to implement it here 
                   because I still don't have the module
                   with a toSeq function *)

如果我在那里实现该方法,我还必须将所有函数实现为该类型的方法,然后该模块将只是调用这些方法的“代理”。通过这种方式,我创建了一个面向对象优先的数据结构,然后创建了一个模块(重载了类型注释)以允许功能优先的使用。我更愿意编写一个功能优先的数据结构(更简洁,因为类型推断可以更好地工作),然后创建一个 OO 包装器,以便更好地支持 C# 等语言的智能感知。该方法符合 F# 的设计指南告诉我们的内容,但接口不能在任何地方实现,只能在类型的初始定义中实现。这种限制迫使我用成员编写整个数据结构。 我一直在寻找示例,我发现FSharp.Core list 中的列表实现完全符合我的要求,但我不能这样做,编译器不会让我这样做。 我几乎可以肯定这是一个设计决定,也许是为了避免鼓励不良做法,我不知道,但我不认为我的愿望是一种不良做法。我也很清楚 fsharp 编译器的线性特性。

如果你们中的任何人知道如何做我想做的事,请告诉我,我会很高兴的。另外,如果你们中的任何人知道为什么我不应该遵循这种方法,我也会很高兴知道。这对其他人来说不是问题一定是有原因的。

提前致谢。

【问题讨论】:

    标签: f#


    【解决方案1】:

    我完全同意这是一个不幸的问题。 F# Core 库中'a list 的源代码中使用的技巧是在类型扩充 中定义接口的实现。当您以这种方式将成员添加到类型时,编译器不会抱怨,但它表示不推荐使用这种方式添加接口的实现。但是,它不会阻止您这样做。以下对我来说编译得很好:

    open System.Collections
    open System.Collections.Generic
    
    type MyCollection<'T> =
      { Data : 'T list }
      interface IEnumerable<'T> 
      interface IEnumerable 
    
    let getEnumerator { Data = d } = 
      (d :> seq<_>).GetEnumerator()
    
    type MyCollection<'T> with 
      interface IEnumerable<'T> with
        member this.GetEnumerator() = getEnumerator this
      interface IEnumerable with
        member this.GetEnumerator() = (getEnumerator this) :> _
    

    这个被弃用的事实有点不幸。我非常喜欢这种风格,我会在有意义的时候使用它。你可以start a discussion about this on F# user voice,也许它可以变成一个正常接受的功能:-)

    【讨论】:

    • 感谢您的回答,我真的很惭愧,我的理解可能会出错。到目前为止,我一直以自己的方式处理这个问题,因为我所有的 F# 代码都是供私人使用的,我不必为 OO 语言提供良好的接口。但最近我在 fsharpx.collections 中添加了一个 SkewBinomialHeap 的实现(仍在拉取请求中),并且必须以更传统和公众可接受的方式来处理这个问题。
    • 是的,该解决方案运行良好。但我担心在该语言的未来版本中,它可能会从弃用变为非法。再次感谢。
    • 我现在知道为什么我认为我做不到。这是因为当我编写初始定义时,编译器已经发出错误信号(方法/s 未实现),而我从未超出此范围。我确实尝试在增强中实现接口,但没有在初始类型中声明它们;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 2015-03-11
    • 1970-01-01
    相关资源
    最近更新 更多