【Go語言入門系列】前面的文章:
- 【Go語言入門系列】(五)指標和結構體的使用
- 【Go語言入門系列】(六)再探函式
- 【Go語言入門系列】(七)如何使用Go的方法?
1. Go是面向物件的語言嗎?
在【Go語言入門系列】(七)如何使用Go的方法?這一文中已經介紹了方法的概念,但這個方法實際上并不是面向物件中的方法,方法實際上是用戶給其定義的型別的增加的新行為,實際上也是個函式,
關于這個問題,官方檔案中有回答:
Yes and no. Although Go has types and methods and allows an object-oriented style of programming, there is no type hierarchy. The concept of “interface” in Go provides a different approach that we believe is easy to use and in some ways more general. There are also ways to embed types in other types to provide something analogous—but not identical—to subclassing. Moreover, methods in Go are more general than in C++ or Java: they can be defined for any sort of data, even built-in types such as plain, “unboxed” integers. They are not restricted to structs (classes).
Also, the lack of a type hierarchy makes “objects” in Go feel much more lightweight than in languages such as C++ or Java.
既是也不是,盡管Go擁有型別和方法,也允許面向物件風格的編程,但它沒有型別層級, 在Go中“介面”的概念提供了不同的方法,我們相信它易于使用且在某些方面更通用, 也有一些在其它型別中嵌入型別的方法,來提供類似(而非完全相同)的東西進行子類化, 此外,Go中的方法比C++或Java中的更通用:它們可被定義為任何種類的資料, 甚至是像普通的“未裝箱”整數這樣的內建型別,它們并不受結構(類)的限制,
此外,型別層級的缺失也使Go中的“物件”感覺起來比C++或Java的更輕量級,
有了這個回答,下面介紹的“繼承”和“重寫”的概念并不是嚴格的面向物件中的繼承和重寫的概念,這里只借用這兩個名詞來表示Go的兩種特性,
2.“繼承”
在面向物件中,繼承是子類和父類之間的關系,子類會繼承父類的公有成員變數和成員方法,
前面提到過,Go允許面向物件風格的編程,那Go如何“繼承”呢?
2.1.“繼承”欄位
在【Go語言入門系列】(五)指標和結構體的使用這一文中,介紹了匿名欄位(也叫嵌入欄位):
package main
import "fmt"
type people struct {
name string
age int
}
type student struct {
people
school string
}
func (s student) say() {
fmt.Printf("我是%s,今年%d歲了,在%s上學,", s.name, s.age, s.school)
}
func main() {
stu := student{people{"行小觀", 1}, "陽光小學"}
stu.say()
}
運行:
我是行小觀,今年1歲了,在陽光小學上學
結構體student中有匿名欄位people,所以student就有了people的name和age欄位,當匿名欄位是一個結構體時,那么該結構體的全部欄位都會被引入當前的結構體中,這是不是很像面向物件中的繼承?子類繼承父類的公有成員變數,
考慮下面一個問題,如果student和people中都有name欄位,那么訪問時,Go語言是如何處理的?
package main
import "fmt"
type people struct {
name string //人名
age int
}
type student struct {
people
name string //學生名
school string
}
func main() {
stu := student{people{"李二狗", 1}, "李向前", "陽光學校"}
fmt.Println(stu.name) //李向前
fmt.Println(stu.people.name) //李二狗
}
此時就出現了欄位沖突,Go會先訪問外層的欄位,比如,stu.name是李向前(外層),stu.people.name是李二狗(內層),
2.2.“繼承”方法
我們通過接收者把函式系結到結構體型別上,這樣的函式稱為方法,方法就在概念上屬于了接收者對應的結構體,
上面通過結構體中匿名欄位實作了“繼承”欄位的效果,對于方法來說,同樣可以,下面是一個實體:
package main
import "fmt"
type people struct {
name string
age int
}
type student struct {
people
school string
}
type programmer struct {
people
language string
}
func (p people) say() {
fmt.Printf("我是%s,今年%d歲了,和我一起學習Go語言吧!\n", p.name, p.age)
}
func main() {
stu := student{people{"行小觀", 1}, "陽光小學"}
stu.say()
prom := programmer{people{"張三", 1}, "藍天建筑有限公司"}
prom.say()
}
運行:
我是行小觀,今年1歲了,和我一起學習Go語言吧!
我是張三,今年1歲了,和我一起學習Go語言吧!
say()方法的接收者是people型別,而結構體student和programmer中都有匿名欄位people,所以stu和prom都能呼叫say()方法,這是不是很像面向物件語言中子類繼承父類的公有方法?
3. “重寫”
3.1. “重寫”欄位
前面已經介紹了如果結構體和作為其欄位的結構體的欄位沖突了如何處理,有了這個特性,我們就可以“重寫”欄位,
package main
import "fmt"
type people struct {
name string //乳名
age int
}
type student struct {
people
name string //大名
school string
}
func (s student) say() {
fmt.Printf("我是%s,今年%d歲了,和我一起學習Go語言吧!\n", s.name, s.age)
}
func main() {
stu := student{people{"李二狗", 1}, "李向前","陽光小學"}
stu.say()
}
運行:
我是李向前,今年1歲了,和我一起學習Go語言吧!
李二狗是乳名,李向前才是大名,自我介紹時說的是大名李向前,如果需要乳名,則使用stu.people.name,
3.2.“重寫”方法
下面是一個實體:
package main
import "fmt"
type people struct {
name string
age int
}
type student struct {
people
school string
}
type programmer struct {
people
language string
}
func (p people) say() { //people的say方法
fmt.Printf("我是%s,今年%d歲了,和我一起學習Go語言吧!\n", p.name, p.age)
}
func (s student) say() { //student重寫people的say方法
fmt.Printf("我是%s,是個學生,今年%d歲了,我在%s上學!\n", s.name, s.age, s.school)
}
func (p programmer) say() { //programmer重寫people的say方法
fmt.Printf("我是%s,是個程式員,今年%d歲了,我使用%s語言!\n", p.name, p.age, p.language)
}
func main() {
stu := student{people{"李向前", 1}, "陽光小學"}
stu.say()
prmger := programmer{people{"張三", 1}, "Go"}
prmger.say()
}
運行:
我是李向前,是個學生,今年1歲了,我在陽光小學上學!
我是張三,是個程式員,今年1歲了,我使用Go語言!
student和programmer“繼承”了people的say()方法,但是不合適,于是各自“重寫”了say()方法,
看到這里,你就理解了官方檔案中的那兩句話是什么意思了,
“盡管Go擁有型別和方法,也允許面向物件風格的編程,但它沒有型別層級”
“型別層級的缺失也使Go中的“物件”感覺起來比C++或Java的更輕量級”
作者簡介
我是行小觀,我會在公眾號『行人觀學』中持續更新Java、Go、資料結構和演算法、計算機基礎等相關文章,
本文章已收錄進系列文章「Go語言入門系列」,本系列從Go語言基礎開始介紹,適合從零開始的初學者,
歡迎關注,我們一起踏上編程的行程,
如有錯誤,還請指正,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/333.html
標籤:Go
