聊聊 Go 語言中的物件導向程式設計
作者:
程式設計拯救世界(ID: CodeWarrior_):專注於程式設計基礎與服務端研發。
我們知道,在 Go 語言中沒有類(Class)的概念,但這並不意味著 Go 語言不支援,畢竟物件導向只是一種程式設計思想。
讓我們回憶一下物件導向的三大基本特徵:
- 封裝:隱藏物件的屬性和實現細節,僅對外提供公共訪問方式
- 繼承:使得子類具有父類的屬性和方法或者重新定義、追加屬性和方法等
- 多型:不同物件中同種行為的不同實現方式
我們一起來看看 Go 語言是如何在沒有類(Class)的情況下實現這三大特徵的。
封裝
「類」
在 Go 語言中可以使用(Structs)對屬性進行封裝,結構體就像是類的一種簡化形式。
例如,我們要定義一個矩形,每個矩形都有長和寬,我們可以這樣進行封裝:
type Rectangle struct {
Length int
Width int
}
方法
既然有了「類」,你可能會問了,那「類」的方法在哪呢?
Go 語言中也有(Methods):Go 方法是作用在接收者(receiver)上的一個函式,接收者是某種型別的變數。因此方法是一種特殊型別的函式。
定義方法的格式如下:
func (recv receiver_type) methodName(parameter_list) (return_value_list) { ... }
上文中我們已經定義了一個矩形 Rectangle
,現在我們要定義一個方法 Area()
來計算它的面積:
package main
import (
"fmt"
)
// 矩形結構體
type Rectangle struct {
Length int
Width int
}
// 計算矩形面積
func (r *Rectangle) Area() int {
return r.Length * r.Width
}
func main() {
r := Rectangle{4, 2}
// 呼叫 Area() 方法,計算面積
fmt.Println(r.Area())
}
上面的程式碼片段輸出結果為 8。
訪問許可權
我們常會說一個類的屬性是公共的還是私有的,在其他程式語言中,我們常用 public
與 private
關鍵字來表達這樣一種訪問許可權。
在 Go 語言中沒有 public
、private
、protected
這樣的訪問控制修飾符,它是透過字母大小寫來控制可見性的。
如果定義的常量、變數、型別、介面、結構、函式等的名稱是大寫字母開頭,這表示它們能被其它包訪問或呼叫(相當於 public
);非大寫開頭就只能在包內使用(相當於 private
)。
訪問未匯出欄位
當遇到只能在包內使用的未匯出欄位時,我們又該如何訪問呢?
和其他面嚮物件語言一樣,Go 語言也有實現 getter
和 setter
的方式:
- 對於
setter
方法使用Set
字首 - 對於
getter
方法只使用成員名
例如我們現在有一個處於 person
包中的 Person
結構體:
package person
type Person struct {
firstName string
lastName string
}
我們可以看到,它的兩個成員變數都是非大寫字母開頭,只能在包內使用,現在我們為其中的 firstName
來定義 setter
與 getter
:
// 獲取 firstName
func (p *Person) FirstName() string {
return p.firstName
}
// 設定 firstName
func (p *Person) SetFirstName(newName string) {
p.firstName = newName
}
這樣一來,我們就可以在 main
包裡設定和獲取 firstName
的值了:
package main
import (
"fmt"
"./person"
)
func main() {
p := new(person.Person)
p.SetFirstName("firstName")
fmt.Println(p.FirstName())
}
/* Output:
firstName
*/
繼承
在 Go 語言中沒有 extends
關鍵字,它使用在結構體中內嵌匿名型別的方法來實現繼承。
匿名型別:即這些型別沒有顯式的名字。
我們定義一個 Engine
介面型別,一個 Car
結構體,讓 Car
結構體包含一個 Engine
型別的匿名欄位:
type Engine interface {
Start()
Stop()
}
type Car struct {
Engine // 包含 Engine 型別的匿名欄位
}
此時,匿名欄位 Engine
上的方法「晉升」成為了外層型別 Car
的方法。我們可以構建出如下程式碼:
func (c *Car) GoToWorkIn() {
// get in car
c.Start()
// drive to work
c.Stop()
// get out of car
}
多型
在物件導向中,多型的特徵為:不同物件中同種行為的不同實現方式。在 Go 語言中可以使用實現這一特徵。
我們先定義一個正方形 Square
和一個長方形 Rectangle
:
// 正方形
type Square struct {
side float32
}
// 長方形
type Rectangle struct {
length, width float32
}
然後,我們希望可以計算出這兩個幾何圖形的面積。但由於他們的面積計算方式不同,我們需要定義兩個不同的 Area()
方法。
於是,我們可以定義一個包含 Area()
方法的介面 Shaper
,讓 Square
和 Rectangle
都實現這個介面裡的 Area()
:
// 介面 Shaper
type Shaper interface {
Area() float32
}
// 計算正方形的面積
func (sq *Square) Area() float32 {
return sq.side * sq.side
}
// 計算長方形的面積
func (r *Rectangle) Area() float32 {
return r.length * r.width
}
我們可以在 main()
函式中這樣呼叫 Area()
:
func main() {
r := &Rectangle{10, 2}
q := &Square{10}
// 建立一個 Shaper 型別的陣列
shapes := []Shaper{r, q}
// 迭代陣列上的每一個元素並呼叫 Area() 方法
for n, _ := range shapes {
fmt.Println("圖形資料: ", shapes[n])
fmt.Println("它的面積是: ", shapes[n].Area())
}
}
/*Output:
圖形資料: &{10 2}
它的面積是: 20
圖形資料: &{10}
它的面積是: 100
*/
由以上程式碼輸出結果可知:不同物件呼叫 Area()
方法產生了不同的結果,展現了多型的特徵。
總結
- 物件導向的三大特徵是:封裝、繼承和多型
- Go 語言使用結構體對屬性進行封裝,結構體就像是類的一種簡化形式
- 在 Go 語言中,方法是作用在接收者(receiver)上的一個函式,接收者是某種型別的變數
- 名稱首字母的大小寫決定了該變數/常量/型別/介面/結構/函式……能否被外部包匯入
- 無法被匯入的欄位可以使用
getter
和setter
的方式來訪問 - Go 語言使用在結構體中內嵌匿名型別的方法來實現繼承
- 使用介面可以實現多型
參考書籍
- 《Go 入門指南》:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1762/viewspace-2824393/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- GO 語言中的物件導向Go物件
- Go物件導向程式設計OOP的實現Go物件程式設計OOP
- SOLID Go Design - Go語言物件導向設計SolidGo物件
- SOLID Go Design - Go 語言物件導向設計SolidGo物件
- 物件導向程式設計物件程式設計
- 開放出版:許式偉《Go語言程式設計》樣章“物件導向程式設計”Go程式設計物件
- 函數語言程式設計 VS 物件導向程式設計函數程式設計物件
- Go語言結構體(struct)物件導向程式設計基礎篇Go結構體Struct物件程式設計
- Scala的物件導向程式設計物件程式設計
- JS物件導向的程式設計JS物件程式設計
- javascript:物件導向的程式設計JavaScript物件程式設計
- iOS 開發之 OOA (物件導向分析) & OOD (物件導向設計)& OOP (物件導向程式設計)iOS物件OOP程式設計
- [.net 物件導向程式設計基礎] (2) 關於物件導向程式設計物件程式設計
- go 併發程式設計案例三 golang 中的物件導向程式設計Golang物件
- 十三、物件導向程式設計物件程式設計
- js物件導向程式設計JS物件程式設計
- 程式設計思想 物件導向程式設計物件
- 十六、物件導向程式設計物件程式設計
- perl 物件導向程式設計物件程式設計
- LotusScript物件導向程式設計物件程式設計
- Javascript 物件導向程式設計JavaScript物件程式設計
- Go 是物件導向的語言嗎?Go物件
- JS物件導向程式設計(一):物件JS物件程式設計
- OOC 物件導向 C 語言程式設計實踐物件程式設計
- 物件導向 vs. 函數語言程式設計物件函數程式設計
- 物件導向程式設計-java語言 第二週程式設計題物件程式設計Java
- [筆記]物件導向的程式設計筆記物件程式設計
- JavaScript 中的物件導向程式設計JavaScript物件程式設計
- 物件導向的JavaScript程式設計 (轉)物件JavaScript程式設計
- Go語言中的TCP/IP網路程式設計GoTCP程式設計
- 聊聊Go語言中的陣列與切片Go陣列
- JavaScript物件導向程式設計理解!JavaScript物件程式設計
- Python物件導向程式設計Python物件程式設計
- 物件導向程式設計C++物件程式設計C++
- Python 物件導向程式設計Python物件程式設計
- Javascript 物件導向程式設計(一)JavaScript物件程式設計
- Javascript 物件導向程式設計(二)JavaScript物件程式設計
- Javascript 物件導向程式設計(三)JavaScript物件程式設計