有没有办法在Ruby中实现mixin或在F#中使用Scala中的特征?
我想要的是基本上将一个模块复制到另一个模块,以便它共享其他模块功能但是关闭以进行修改。或者,一个OOP的思考方式,我想要多重继承,除了父对象不能被修改。
答案 0 :(得分:14)
您可以滥用inline
和成员约束来进行鸭子打字,这可以获得mixins的一些好处。例如,您可以翻译此Ruby代码(取自this tutorial):
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"
到此:
type Phonograph(id, name) =
member x.Id : int = id
override x.ToString() = name
type EightTrack(id, name) =
member x.Id : int = id
override x.ToString() = name
module Debug =
let inline whoAmI x =
sprintf "%s (%d) : %s"
(^T : (member GetType : unit -> Type) x).Name
(^T : (member Id : int with get) x)
(^T : (member ToString : unit -> string) x)
let ph = Phonograph(537766170, "West End Blues")
let et = EightTrack(537765860, "Surrealistic Pillow")
Debug.whoAmI ph //"Phonograph (537766170) : West End Blues"
Debug.whoAmI et //"EightTrack (537765860) : Surrealistic Pillow"
与不需要公共基类或接口的扩展方法相比,它具有(可论证的)优势。关于您之前关于open
关键字的问题,您可以有几个模块定义whoAmI
,而最后一个open
将隐藏前一个模块。通过这种方式,您可以“混合”您想要的模块。 F#核心库使用与checked operators类似的方法。
答案 1 :(得分:2)
Ruby mixins最好使用.NET框架中的扩展方法(类型扩展)进行模拟。我不相信F#有任何特殊的语言特征,更像是mixins,traits或多重继承。
请参阅此问题:How do I create an extension method (F#)?
此描述:http://msdn.microsoft.com/en-us/library/dd233211.aspx
为了速度,这是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())