1 概述
結構體的基本語法請參見:Go語言中結構體的使用-第1部分結構體。
結構體除了是一個複合數據之外,還用來做面向對象編程。Go 語言使用結構體和結構體成員來描述真實世界的實體和實體對應的各種屬性。也就意味着結構體類型可以類比爲其他語言中的“類class”, 而結構體數據可以類比爲其他語言中的 “對象”。
本文就說說結構體中,面向對象的部分。
2 構造工廠函數
在面向對象編程中,實例化對象時往往需要完成很多業務邏輯,例如初始數據合理性,獲取需要的資源等。在經典的OOP程序中,都會提供構造方法,用於在實例化對象時完成特定功能。
Go語言中,沒有class,因此沒有典型意義的構造方法。但我們可以定義一個函數,用來實例化結構體對象,在函數內完成特定功能,實現構造函數的功能,這就是構造工廠函數。演示如下:
type Product struct {
Name string
Price float64
}
func NewProduct(name string, price float64) *Product {
// 此處完成初始化業務邏輯
// 得到Product對象
return &Product{
Name: name,
Price: price,
}
}
// 需要 Product 對象時:
p := NewProduct("ThinkPad T480", 8008)
注意,在OOP編程中,通常認爲對象是引用用傳遞,因此我們的構造函數返回的是 *Product
同時函數內使用 &Product
,這樣得到的對象爲引用傳遞(Go語言對結構體類型自動解析引用)。
3 成員方法(接收器)
若要爲成員增加方法,需要在函數上定義接收器,用來接收調用該方法的成員對象。接收器定義如下:
func (p *Product) Sale() {
fmt.Println("Product: ", p.name, " is on Sale")
}
語法中,(p *Product)
就是接收器。通過定義可知,該接收器可以讓函數接受一個 *Product
類型的參數,也就是調用該函數的對象。調用方法爲:
pro := &Product{
name: "ThinkPad T480"
}
// 當作成員去調用
// 調用時,將調用函數的 pro,作爲參數傳遞給函數 Run 的接收器 m。這樣就可以訪問 pro 對象了。
pro.Sale()
同樣,面向對象中對象通常爲引用類型,因此接收器的定義也是 *Product
的引用類型。
4 繼承,內嵌結構體
Go語言中結構體對象間的繼承,通過內嵌結構體語法實現。演示:
type Product struct {
Name string
Price float64
}
func (p *Product) Sale() {
fmt.Println("Product: ", p.name, " is on Sale")
}
type Book struct {
// 嵌入Product結構體
Product
Author string
Publish string
}
定義 Book 時,內嵌了 Product 結構體。其中 Book 稱爲子結構體(派生,擴展),Product成爲父結構體(基礎)。實例化的 Book 結構體對象,可以直接訪問 Product 結構體中定義的成員包括屬性和方法。演示:
v := &Book{}
// 訪問內嵌結構體屬性
v.Name = "笑傲江湖"
v.Author = "金庸"
// 調用內嵌結構體方法
v.Sale()
內嵌還支持:
多繼承,可以同時內嵌多個結構體,稱之爲多繼承。但要保證所繼承的結構體間沒有同名成員,否則出錯。
間接訪問,字結構體對象支持通過父結構體對象訪問繼承的成員,語法爲 v.Product.Name
,效果與 v.Name
一致。可以理解爲是一種快捷語法。
直接初始化,可以直接爲內嵌結構體提供初始化操作。演示爲:
p := &Book{
Product: &Product{
Name: "天龍八部"
Price: 42.8
}
Author: "金庸"
}
5 重寫,override
在內嵌繼承中,若子與父結構體存在同名成員,實例化的子結構體成員,訪問到的是字結構體定義的成員。這個現象稱之爲重寫override。演示:
type Product struct {
Name string
Price float64
}
func (p *Product) Sale() {
fmt.Println("Product: ", p.name, " is on Sale")
}
type Book struct {
// 嵌入Product結構體
Product
Author string
Publish string
Price float64
}
v := &Book{}
// 訪問內嵌結構體屬性
// 以下代碼訪問的是 Book 中定義的 Price 屬性
v.Price = 42.8
// 測試:
fmt.Println(v.Product.Price) // 結果爲 0
注意,繼承是一個查找 過程。先在當前結構體對象中查找,如果沒有向內嵌結構體中查找,直到最內層內嵌結構體。重寫就是由於在當前結構體對象中查找到了,就不需要再去嵌入結構體對象中查找了,不是一個成員替換過程。
結構體,實例化,繼承,重寫示意圖如下:
以上就是結構體提供的關於OOP中的語法。OOP編程還會涉及到接口,反射等技術。
結構體第二部分完!
原文出自:小韓說課
微信關注:小韓說課