Go(8) - interface and polymorphism
interface 定義一些需要具備的函式,讓滿足 interface 規範的物件具有特定功能。
1. 定義一個 interface:
定義一個 interface 叫 IInfomation,具有 Info() 簽名的物件可以被當成是具有 IInfomation 的能力。
定義一個 struct 叫 Computer 並添加 Info(),即 Computer has-a Info()。
type IInfomation interface { Info() string // (1) 宣告需具備的函式,不包含實作 (可宣告多個函式) } type Computer struct { prodictID string } func (c Computer) Info() string { // (2) 實作 Info() string,所以 Computer has-a Info return fmt.Sprintf("ProductID: %s", c.prodictID) } func GetInfo(i IInfomation) { // (3) 呼叫物件 i,i 具有 IInfomation 的功能所以有 i.Info() fmt.Println(i.Info()) } func main() { computer := Computer{"12345"} GetInfo(computer)// (4) computer.Info() }
2. 什麼是 Polymorphism:
參考 Object-Oriented Software Engineering 對 Polymorphism 的解釋。
If an instance sends a stimulus to another instance, but does not have to be aware of which class the receiving instance belongs to, we say that we have polymorphism.
白話的來說我們宣告函式時只在乎物件是否具有我們要求的能力,這樣可以讓程式碼較為簡潔。
考慮下面的例子:
func (c Computer) Info() string { // Computer 實作 Info() string } func (c Cat) Info() string { // Cat 實作 Info() string } !! 注意 !! Go 實際上不支援 overloading func GetInfo(c Computer) { fmt.Println(i.Info()) } func GetInfo(c Cat) { fmt.Println(i.Info()) }
有 IInfomation 的 polymorphism 我們確保物件具有 Info(),所以變成
func GetInfo(i IInfomation) { fmt.Println(i.Info()) } // Computer 和 Cat 都有 Info GetInfo(computer) GetInfo(cat)
3. 滿足 Polymorphism 的情形:
有兩種情形我們可以確保物件具有特定的能力。
- 透過繼承實現的 is-a 關係
- 透過介面實現的 has-a 關係
Go 中無法透過組合實現 Polymorphism (組合不會讓 Go 有 is-a 關係)。
一般有繼承能力的語言 (如: Java, Scala),繼承的同時會形成 is-a 關係。例如 Dog 繼承 Animal,所以 Dog is a Animal。繼承後子類 Dog 可以使用所有父類 Animal 的函式。
組合 Animal 可以確定物件具有某些功能,但 Go 沒有轉型的能力。考慮下面例子:
package main import "fmt" type Animal struct { name string age int } func (a *Animal) WhoAmI() string { return fmt.Sprintf("Name: %s, age: %d", a.name, a.age) } type Dog struct { Animal Breed string } func Introduction(a Animal) { a.WhoAmI() } func main() { d := Dog{Animal{"White", 10}, "Beagles"} fmt.Println(d.WhoAmI()) Introduction(d) // cannot use d (type Dog) as type Animal }
由上例可知 Go 實現了類似 prototype chain 的查找但無法把 Dog 轉型成 Animal。
通常語言容許滿足多個介面但只允許單一繼承,所以實務上最好透過介面實現 Polymorphism。
留言
張貼留言