F#コードは多くの場合、型に対するパターンマッチのようです。もちろん
match opt with
| Some val -> Something(val)
| None -> Different()
よくあるようです。
しかし、OOPの観点から見ると、それはランタイムタイプチェックに基づく制御フローに非常によく似ており、通常は眉をひそめます。わかりやすく言うと、OOPではおそらくオーバーロードを使用することをお勧めします。
type T =
abstract member Route : unit -> unit
type Foo() =
interface T with
member this.Route() = printfn "Go left"
type Bar() =
interface T with
member this.Route() = printfn "Go right"
これは確かにより多くのコードです。OTOH、私のOOP-yの心には構造的な利点があるようです:
- 新しい形式への拡張
T
は簡単です。 - ルートを選択する制御フローの重複を見つけることを心配する必要はありません。そして
- ルートの選択は不変です。一度
Foo
手に入れれば、Bar.Route()
の実装を心配する必要はありません。
表示されていない型に対するパターンマッチングの利点はありますか?それは慣用的と考えられますか、それとも一般的に使用されない機能ですか?
But from an OOP perspective, that looks an awful lot like control-flow based on a runtime type check, which would typically be frowned on.
は、あまりにも独断的に聞こえます。場合によっては、オペレーションを階層から分離する必要があります。多分1)階層にopを追加できないb / c階層を所有していない。2)opにしたいクラスが階層と一致しません。3)opを階層に追加することはできますが、ほとんどのクライアントが使用しないがらくたの塊で階層のAPIを乱雑にしたくない場合は、b / cをしたくありません。