2

ここに 2 つの F# シナリオがあります。私は抽象クラスを持っています:

type IAbstractObj =
    abstract DoSomething : bool -> bool

シナリオ 1:

インターフェイスを型に実装します。

type ConcreteObj = 
    interface IAbstractObj with
        member this.DoSomething bool = true

これは、インスタンス化によってアプリケーションで使用されます。

let foo = new ConcreteObj();

シナリオ 2:

タイプのインスタンスを let バインディングでバインドし、それを「フリー関数ホルダー」として使用します。

let ConcreteObj = {
    new IAbstractObj with
        member this.DoSomething bool = true
}

そしてそれを次のように使用します:

let foo = ConcreteObj

これらの用途の違いは何ですか? いずれの場合も、型は追加のランタイム状態を保持する必要はありません。

  • パフォーマンスの違いはありますか (ごくわずか)? 「let」バインディングを含むモジュールでは、メモリはアプリケーションの他の部分で実際に評価されるバインディングにのみ割り当てられますか?
  • シナリオ 1 では、(ステートレスであっても) インスタンスへのポインターを保持するために少量のメモリを割り当てますか?

私のアプリケーションにとってはかなり重要です。私は、インスタンスの状態を保持しないバリデーターとシリアライザーに多くのインターフェースを使用しています。私の C# バックグラウンドでは、インターフェイスを継承するクラスのインスタンスを作成しなければならないことに慣れてます。これは、パラメーターのないコンストラクターがあり、明らかに本質的に静的関数の所有者にすぎない場合でも同様です。

4

2 に答える 2

3

これらのいずれよりも慣用的なオプションがあります。オプションごとに新しいタイプを作成する代わりに、関数である 2 つのメンバーを持つレコード タイプを作成するだけです。コメントでほぼ自分で定義しました:

type serializer<'a, 'b> = 
    { Serialize : 'a -> 'a Option
      Deserialize: 'b -> 'b Option}

let concrete = { Serialize = (fun (x)->Some(x)); Deserialize = (fun (x)->Some(x)) }

したがって、これを消費しているものは何でもserializer.

于 2013-09-19T19:32:54.500 に答える
3

この 2 つの主な違いは、オブジェクト式には、実装するインターフェイスまたは抽象クラスの静的な型があることです。一方、クラスベースのインターフェイスの実装は明示的であり、インターフェイス メンバーにアクセスするにはキャストが必要です。

単純なインターフェイスの実装では、通常、クラスよりもオブジェクト式を選択することをお勧めします。

(FWIW、パフォーマンスに関する懸念は重要ではないと思います。)

于 2013-09-19T19:09:44.013 に答える