混合或特征于F#

混合或特征于F#,f#,functional-programming,F#,Functional Programming,有没有办法在Ruby中实现mixin,或者在F#中实现Scala的trait 我想要的基本上是将一个模块复制到另一个模块中,这样它就可以共享其他模块的功能,但可以关闭以进行修改。或者,从面向对象的角度来看,我想要多重继承,但父对象不能修改 Ruby mixin最好用.NET framework中的扩展方法(类型扩展)来模拟。我不认为F#有任何更接近混合、特征或多重继承的特殊语言特征 见这个问题: 以及以下描述: 为了提高速度,以下是MSDN上给出的示例: module MyModule1 =

有没有办法在Ruby中实现mixin,或者在F#中实现Scala的trait


我想要的基本上是将一个模块复制到另一个模块中,这样它就可以共享其他模块的功能,但可以关闭以进行修改。或者,从面向对象的角度来看,我想要多重继承,但父对象不能修改

Ruby mixin最好用.NET framework中的扩展方法(类型扩展)来模拟。我不认为F#有任何更接近混合、特征或多重继承的特殊语言特征

见这个问题:

以及以下描述:

为了提高速度,以下是MSDN上给出的示例:

module MyModule1 =

    // Define a type.
    type MyClass() =
      member this.F() = 100

    // Define type extension.
    type MyClass with
       member this.G() = 200

module MyModule2 =
   let function1 (obj1: MyModule1.MyClass) =
      // Call an ordinary method.
      printfn "%d" (obj1.F())
      // Call the extension method.
      printfn "%d" (obj1.G())

您可以滥用
inline
和成员约束来进行duck键入,这可以让您获得mixin的一些好处。例如,您可以翻译此Ruby代码(摘自):

为此:

类型留声机(id、名称)=
成员x.Id:int=Id
重写x.ToString()=名称
输入EightTrack(id、名称)=
成员x.Id:int=Id
重写x.ToString()=名称
模块调试=
让我们来看看=
sprintf“%s(%d):%s
(^T:(成员GetType:unit->Type)x).名称
(^T:(成员Id:int和get)x)
(^T:(成员到字符串:单位->字符串)x)
让ph=留声机(537766170,“西区布鲁斯”)
let et=EightTrack(537765860,“超现实主义枕头”)
Debug.whoAmI ph/“留声机(537766170):西区布鲁斯”
Debug.whoAmI et/“EightTrack(537765860):超现实主义枕头”
与不需要公共基类或接口的扩展方法相比,它具有(有争议的)优势。关于您之前关于
open
关键字的问题,您可以有几个模块定义
whoAmI
,最后一个
open
ed模块将覆盖前面的模块。通过这种方式,您可以排序“混合”您想要的模块。F#core库使用了类似的方法。

有些相关:
module Debug
  def whoAmI?
    "#{self.type.name} (\##{self.id}): #{self.to_s}"
  end
end
class Phonograph
  include Debug
  # ...
end
class EightTrack
  include Debug
  # ...
end
ph = Phonograph.new("West End Blues")
et = EightTrack.new("Surrealistic Pillow")
ph.whoAmI?  »   "Phonograph (#537766170): West End Blues"
et.whoAmI?  »   "EightTrack (#537765860): Surrealistic Pillow"