如何使用 FP 實現 OOP 的 Polymorphism ?
OOP 最自豪的就是 Polymorphism (多型),若使用 FP,該如何實現這個 OOP 的招牌菜呢?
Version
macOS High Sierra 10.13.3
.NET Core SDK 2.1.101
C# 7.2
F# 4.1
Shape Again
在眾多 OOP 書中,都會看到這個經典 Shape,這是展示 OOP 經典的 Polymorphism 與 Virtual / Override 的經典範例。
Circle
、Rectangle
與Triangle
都抽象化成Shape
這個 abstract class- 因為每個形狀計算面積的公式都不同,因此在
Shape
開 abstract method,再由Circle
、Rectangle
與Triangle
各自實作Area()
- 最後將
Circle
、Rectangle
與Triangle
都擺進List
,一一的呼叫每個形狀的Area()
,因為 OOP 的 Polymorphism 機制,所以我們不必去判斷 class 型別,自己會執行對的 class 與 method
這就是我們熟悉的 Polymorphism。
將分別以 C# 與 F# 實作此需求,體會一下 OOP 與 FP 的差異。
CSharp
Shape.cs
1 | namespace ConsoleApp |
定義 Shape
abstract class,其中 Area()
為 abstract method,因為每個形狀計算面積的公式不同,必須由子類別去實作。
Circle.cs
1 | namespace ConsoleApp |
Circle
由 constructor 傳入 radius
,並 override Area()
計算圓形面積。
Rectangle.cs
1 | namespace ConsoleApp |
Rectangle
由 constructor 傳入 width
與 height
,並 override Area()
計算矩形面積。
Triangle.cs
1 | namespace ConsoleApp |
Triangle
由 constructor 傳入 base
與 height
,並 override Area()
計算三角形面積。
Program.cs
1 | using System; |
將 Circle
、Rectangle
與 Triangle
3 個物件都塞入 List
,使用 foreach
執行每個物件的 Area()
,不用判斷型別,就自動會執行對的物件,這就是我們熟知的 Polymorphism。
各自算出各形狀的面積。
FSharp
Program.fs
1 | open System |
第 3 行
1 | type Shape = |
定義 Shape
union,包含 Circle
、Rectangle
與 Triangle
三個 case。
至於三個型別的資料,則直接在 case 後面接 of
表示。
我們看到 C# 必須使用
abstract class
與繼承
,才能描述Shape
與Circle
、Rectangle
與Triangle
之間的抽象關係,但 F# 使用union
只要 4 行即可,而且還是強型別
第 8 行
1 | let area shape = |
至於 Area()
的多型怎麼辦 ?
只要使用 Pattern Matching 判斷 shape
的型別,各自實作其面積公式即可。
我們看到 C# 必須使用 virtual / override 機制才能實現 Polymorphism,但 F# 使用 Pattern Matching 只要 5 行即可
15 行
1 | let main argv = |
不必使用 foreach
,只要以 Pipeline 方式透過 List.map
執行每個物件的 area()
,再以 Pipeline 方式透過 List.iter
將計算的結果交給 printfn
顯示。
C# 雖然也可以使用 LINQ 方式,與 F# 極為類似,不過 LINQ 已經屬於 functional ,不是傳統 OOP 的 imperative
Conclusion
- FP 使用
union
即可實作出 OOP 的繼承
概念 - FP 使用 Pattern Matching 即可實作出 OOP 的
virtual/override
概念 - OOP 是將 data 與 function 合一,都包在 class 內;FP 是將 data 與 function 分離,data 歸 Type,function 還是 function
- F# 的程式碼明顯比 C# 精簡
- 並不是要比較哪個語言的優劣,只想強調 OOP 與 FP 以不同的思維,都可以實作出 Polymorphism