前言
Go 不是一個典型的物件導向程式語言 (Object Oriented Programming, OOP), 所謂的 OOP 三大精神 "封裝", "繼承", 與 "多形" 在Go語言中其實並沒有被完整的實現, 取而代之的是以結構來代替類別, 以組合來代替繼承, 以及介面實作來達到多形結構與類別的差異
Go 允許將相關的資料組織在同一個結構 (struct) 裡, 甚至還可以為其定義方法, 這個作法跟其他 OOP 語言 (如 C# ) 將資料封裝在類別裡的概念很像type User struct {
Hight int
Weight int
Name string
}
func (p * User) GetBMI() int {
return p.Weight / p. Hight * p. Hight
}
差別是結構沒有建構子可以用, 所以通常是要自己寫一個 New_ _ _( ) 的函式來實現相關的初始化的動作func NewUser(h, w int, name string) *User{
p:= &Page{Hight: h, Weight: w}
if name == "" {
p.Name = "Unknown" // set default value
}
return p
}
組合 Composition
Go 沒有繼承, 若想要重用程式碼必須以 has-a 的方式將其他結構的資料嵌入 (Type Embedding)type BusinessUser struct {
User // <------------------ type embedding
CreditCarNumber string
}
func NewBusinessUser(h, w int, name, cred string) *User{
if cred == "" {
return nil
}
p:= &BusinessUser{Hight: h, Weight: w, CreditCarNumber: cred}
if name == "" {
p.Name = "Unknown" // set default value
}
return p
}
多形
由於 Go 沒有繼承, 所以不能像傳統的 OOP 一樣透過繼承的方式來實現多形, 但 Go 還是可以透過實作介面的方式做到多形多形多行允許使用同一個介面來操作不同的實例, 藉以降低物件之間的依賴程度並提升程式架構的彈性
type IUser interface { // <-------------------定義介面
GetUserName() string
}
type User struct {
Hight int
Weight int
Name string
}
func (p * User) GetUserName() string { // <-----------------有實作介面
return p.Name
}
因為 User 有實作介面 IUser 裡的所有函式, 所以可以將 User 的實例直接傳進底下的函式 SaveUser 中使用, 而對於 SaveUser 來說, 完全不需要知道傳進來的實例是什麼
func SaveUser(user IUser) {
fmt.Println( user.GetUserName() )
}
留言
張貼留言