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。

留言
張貼留言