拡張プロパティ(F#)
F#では既存の型を拡張して、プロパティを追加することができます。
今回はいくつか使い方を紹介します。
Getterのみ
Listを拡張してみます。
ジェネリックなクラスは拡張できないので、ベースのIListを拡張します。
Countの2倍の値を返すCountDoubleを実装してみます。
open System.Collections open System.Collections.Generic type IList with member this.DoubleCount = this.Count * 2 [<EntryPoint>] let main argv = let x = List<int>([ 1; 2; 3 ]) let s = x.DoubleCount // 6 0
Setter対応
F#基本的にImmutableであるため、Setterを実装することは稀です。
ただ、利用する機会がある可能性があるので実装してみます。
型拡張は原理的にはstaticな関数を追加しているだけなので、fieldを追加することができません。
そこでインスタンスをキーとして状態を保持するDictionaryを用意します。
しかしDictionaryを利用するとインスタンスが参照され続けるので、弱参照で保持するConditionalWeakTableを利用します。
open System.Collections open System.Collections.Generic open System.Runtime.CompilerServices type ListState = { mutable Name : string } let initialListState = { Name = "name" } let listStates = ConditionalWeakTable<IList, ListState>() let getListState x = listStates.GetValue(x, ConditionalWeakTable.CreateValueCallback(fun _ -> initialListState)) type IList with member this.Name with get() = (getListState this).Name and set(value) = (getListState this).Name <- value [<EntryPoint>] let main argv = let x = List<int>([ 1; 2; 3 ]) x.Name <- "NewList" printfn "%s" x.Name 0