溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Go語(yǔ)言是面向?qū)ο笳Z(yǔ)言嗎

發(fā)布時(shí)間:2022-01-18 10:17:38 來(lái)源:億速云 閱讀:95 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“Go語(yǔ)言是面向?qū)ο笳Z(yǔ)言嗎”的相關(guān)知識(shí),小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“Go語(yǔ)言是面向?qū)ο笳Z(yǔ)言嗎”文章能幫助大家解決問(wèn)題。

1. Go是面向?qū)ο蟮恼Z(yǔ)言嗎?

在【Go語(yǔ)言入門系列】(七)如何使用Go的方法?這一文中已經(jīng)介紹了方法的概念,但這個(gè)方法實(shí)際上并不是面向?qū)ο笾械姆椒ā7椒▽?shí)際上是用戶給其定義的類型的增加的新行為,實(shí)際上也是個(gè)函數(shù)。

關(guān)于這個(gè)問(wèn)題,官方文檔中有回答:

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擁有類型和方法,也允許面向?qū)ο箫L(fēng)格的編程,但它沒(méi)有類型層級(jí)。 在Go中“接口”的概念提供了不同的方法,我們相信它易于使用且在某些方面更通用。 也有一些在其它類型中嵌入類型的方法,來(lái)提供類似(而非完全相同)的東西進(jìn)行子類化。 此外,Go中的方法比C++或Java中的更通用:它們可被定義為任何種類的數(shù)據(jù)。 甚至是像普通的“未裝箱”整數(shù)這樣的內(nèi)建類型。它們并不受結(jié)構(gòu)(類)的限制。

此外,類型層級(jí)的缺失也使Go中的“對(duì)象”感覺(jué)起來(lái)比C++或Java的更輕量級(jí)。

有了這個(gè)回答,下面介紹的“繼承”和“重寫”的概念并不是嚴(yán)格的面向?qū)ο笾械睦^承和重寫的概念。這里只借用這兩個(gè)名詞來(lái)表示Go的兩種特性。

2.“繼承”

在面向?qū)ο笾?,繼承是子類和父類之間的關(guān)系,子類會(huì)繼承父類的公有成員變量和成員方法。

前面提到過(guò),Go允許面向?qū)ο箫L(fēng)格的編程。那Go如何“繼承”呢?

2.1.“繼承”字段

在【Go語(yǔ)言入門系列】(五)指針和結(jié)構(gòu)體的使用這一文中,介紹了匿名字段(也叫嵌入字段):

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上學(xué)。", s.name, s.age, s.school)
}

func main() {
	stu := student{people{"行小觀", 1}, "陽(yáng)光小學(xué)"}
	stu.say()
}

運(yùn)行:

我是行小觀,今年1歲了,在陽(yáng)光小學(xué)上學(xué)

結(jié)構(gòu)體student中有匿名字段people,所以student就有了peoplenameage字段。當(dāng)匿名字段是一個(gè)結(jié)構(gòu)體時(shí),那么該結(jié)構(gòu)體的全部字段都會(huì)被引入當(dāng)前的結(jié)構(gòu)體中。這是不是很像面向?qū)ο笾械睦^承?子類繼承父類的公有成員變量。

考慮下面一個(gè)問(wèn)題,如果studentpeople中都有name字段,那么訪問(wèn)時(shí),Go語(yǔ)言是如何處理的?

package main

import "fmt"

type people struct {
	name string //人名
	age int
}

type student struct {
	people
	name string //學(xué)生名
	school string
}

func main() {
	stu := student{people{"李二狗", 1}, "李向前", "陽(yáng)光學(xué)校"}
	fmt.Println(stu.name) //李向前
	fmt.Println(stu.people.name) //李二狗
}

此時(shí)就出現(xiàn)了字段沖突,Go會(huì)先訪問(wèn)外層的字段。比如,stu.name李向前(外層),stu.people.name李二狗(內(nèi)層)。

2.2.“繼承”方法

我們通過(guò)接收者把函數(shù)綁定到結(jié)構(gòu)體類型上,這樣的函數(shù)稱為方法,方法就在概念上屬于了接收者對(duì)應(yīng)的結(jié)構(gòu)體。

上面通過(guò)結(jié)構(gòu)體中匿名字段實(shí)現(xiàn)了“繼承”字段的效果,對(duì)于方法來(lái)說(shuō),同樣可以。下面是一個(gè)實(shí)例:

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歲了,和我一起學(xué)習(xí)Go語(yǔ)言吧!\n", p.name, p.age)
}

func main() {
	stu := student{people{"行小觀", 1}, "陽(yáng)光小學(xué)"}
	stu.say()
	prom := programmer{people{"張三", 1}, "藍(lán)天建筑有限公司"}
	prom.say()
}

運(yùn)行:

我是行小觀,今年1歲了,和我一起學(xué)習(xí)Go語(yǔ)言吧!
我是張三,今年1歲了,和我一起學(xué)習(xí)Go語(yǔ)言吧!

say()方法的接收者是people類型,而結(jié)構(gòu)體studentprogrammer中都有匿名字段people,所以stuprom都能調(diào)用say()方法。這是不是很像面向?qū)ο笳Z(yǔ)言中子類繼承父類的公有方法?

3. “重寫”

3.1. “重寫”字段

前面已經(jīng)介紹了如果結(jié)構(gòu)體和作為其字段的結(jié)構(gòu)體的字段沖突了如何處理。有了這個(gè)特性,我們就可以“重寫”字段。

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歲了,和我一起學(xué)習(xí)Go語(yǔ)言吧!\n", s.name, s.age)
}

func main() {
	stu := student{people{"李二狗", 1}, "李向前","陽(yáng)光小學(xué)"}
	stu.say()
}

運(yùn)行:

我是李向前,今年1歲了,和我一起學(xué)習(xí)Go語(yǔ)言吧!

李二狗是乳名,李向前才是大名。自我介紹時(shí)說(shuō)的是大名李向前。如果需要乳名,則使用stu.people.name。

3.2.“重寫”方法

下面是一個(gè)實(shí)例:

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歲了,和我一起學(xué)習(xí)Go語(yǔ)言吧!\n", p.name, p.age)
}

func (s student) say() { //student重寫people的say方法
	fmt.Printf("我是%s,是個(gè)學(xué)生,今年%d歲了,我在%s上學(xué)!\n", s.name, s.age, s.school)
}

func (p programmer) say() { //programmer重寫people的say方法
	fmt.Printf("我是%s,是個(gè)程序員,今年%d歲了,我使用%s語(yǔ)言!\n", p.name, p.age, p.language)
}

func main() {
	stu := student{people{"李向前", 1}, "陽(yáng)光小學(xué)"}
	stu.say()
	prmger := programmer{people{"張三", 1}, "Go"}
	prmger.say()
}

運(yùn)行:

我是李向前,是個(gè)學(xué)生,今年1歲了,我在陽(yáng)光小學(xué)上學(xué)!
我是張三,是個(gè)程序員,今年1歲了,我使用Go語(yǔ)言!

studentprogrammer“繼承”了peoplesay()方法,但是不合適,于是各自“重寫”了say()方法。

看到這里,你就理解了官方文檔中的那兩句話是什么意思了。

“盡管Go擁有類型和方法,也允許面向?qū)ο箫L(fēng)格的編程,但它沒(méi)有類型層級(jí)”

“類型層級(jí)的缺失也使Go中的“對(duì)象”感覺(jué)起來(lái)比C++或Java的更輕量級(jí)”

關(guān)于“Go語(yǔ)言是面向?qū)ο笳Z(yǔ)言嗎”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI