11

Rubyでミックスインを実現したり、F#でScalaのトレイトを実現したりする方法はありますか?

私が欲しいのは、基本的に1つのモジュールを別のモジュールにコピーして、他のモジュールの機能を共有するが、変更のために閉じられるようにすることです。または、OOPの考え方ですが、親オブジェクトを変更できないことを除いて、多重継承が必要です。

4

2 に答える 2

14

ダックタイピングを行うためにメンバーの制約を悪用することができinlineます。これにより、ミックスインの利点のいくつかが得られます。たとえば、このRubyコード(このチュートリアルから取得)を翻訳できます。

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#コアライブラリは、チェックされた演算子を使用した同様のアプローチを使用します。

于 2012-07-13T20:30:22.377 に答える
2

Rubyミックスインは、.NET Frameworkの拡張メソッド(型拡張)を使用してエミュレートするのが最適です。F#には、ミックスイン、特性、または多重継承にさらに類似した特別な言語機能があるとは思いません。

この質問を参照してください:拡張メソッド(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())
于 2012-07-13T18:32:51.823 に答える