Wygląda na to, że kod F # często wzoruje dopasowania względem typów. Na pewno
match opt with
| Some val -> Something(val)
| None -> Different()
wydaje się powszechne.
Ale z punktu widzenia OOP wygląda to bardzo podobnie do przepływu kontroli opartego na sprawdzeniu typu środowiska wykonawczego, na którym zwykle nie można się zgodzić. Aby to przeliterować, w OOP prawdopodobnie wolisz użyć przeciążenia:
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"
To z pewnością więcej kodu. OTOH, moim zdaniem OOP-y ma zalety strukturalne:
- rozszerzenie do nowej formy
T
jest łatwe; - Nie muszę się martwić znalezieniem duplikatu przepływu sterowania wyborem trasy; i
- wybór trasy jest niezmienny w tym sensie, że kiedy mam
Foo
pod ręką, nigdy nie muszę się martwićBar.Route()
implementacją
Czy są zalety dopasowywania wzorców do typów, których nie widzę? Czy jest to uważane za idiomatyczne, czy może nie jest powszechnie używane?
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.
- brzmi zbyt dogmatyczne. Czasami chcesz oddzielić swoje operacje od swojej hierarchii: może 1) nie możesz dodać operacji do hierarchii b / c, której nie posiadasz; 2) klasy, które chcesz mieć, nie pasują do twojej hierarchii; 3) możesz dodać op do swojej hierarchii, ale nie chcesz b / c, że nie chcesz zaśmiecać interfejsu API swojej hierarchii bzdurami, których większość klientów nie używa.