私はStreamReader
を使ってテキストファイルを読み込んで処理することを仕事とするFileReader
クラスを持っています。ユニットテストを容易にするために、このクラスに型パラメータを指定して、StreamReader
をFakeReader
に交換して、ファイルシステムと実際にはやり取りしないでください(OutOfMemory
などの例外がスローされるため、テストできますエラー処理はFileReader
)。 、ReadLine()
F#:型パラメータとしてデフォルトのコンストラクタがないクラス?
type FileReader<'Reader> =
member this.Read file =
use sr = new 'Reader(file)
while not sr.EndOfStream do
printfn "%s" <| sr.ReadLine()
と単純にファイル名を取るコンストラクタ、EndOfStream
プロパティのゲッターを持つようにFakeReader
を定義します。
理想的には、私は(わかりやすくするために矮小)このようなFileReader
何かを定義したいのですがメソッド、および空のDispose()
メソッドです。しかし、F#には、"Calls to object constructors on type parameters cannot be given arguments."
を含むこの型定義に関するいくつかの苦情があります。StreamReader
にはデフォルトのコンストラクタがないので、このアプローチは無駄なようです。
type FakeReader() =
inherit StreamReader("") with
override this.ReadLine() = "go away"
member this.EndOfStream = false
member this.Dispose() =()
し、必要に応じてFakeReader
新しいまたは新規StreamReader
のいずれかを返すファクトリメソッドを使用します。私は仕事にこれを得ている
これまでのところ唯一の方法は、StreamReader
からFakeReader
を継承することです。
type ReaderType = Fake | SR
let readerFactory (file : string, readerType) =
match readerType with
| Fake -> new FakeReader() :> StreamReader
| SR -> new StreamReader(file)
type FileReader(readertype) =
member this.Read file =
use sr = readerFactory(file, readertype)
while not sr.EndOfStream do
printfn "%s" <| sr.ReadLine()
これはかなりエレガントではないようです。型パラメータでこれを行う方法はありますか?ありがとうございます。
は、あなたが実際にそれがベースのOOPになりたいかまたは任意の他のより機能的なアプローチはまたあなたのために動作します:これは、新しい
TextReader
クラスを実装するよりもかなり簡単ですか? – Ankurより機能的なアプローチは実際には素晴らしいでしょう。私は、長年の命令的な土地のためにOOPの松葉杖に戻ってしまう傾向があります。 – FSharpN00b