我的讀者應(yīng)該大多數(shù)都是java或者php的從業(yè)者揖曾,不知道寫java寫php這么多年是否找到對象尾序,沒找到也沒關(guān)系刺彩,總不能在一棵樹上吊死迷郑,我們也可以來 Go 這邊看看,說不定會有新發(fā)現(xiàn)创倔。
我記得才學(xué)習(xí)golang的時候嗡害,都說go語言是不支持面向?qū)ο蟮模莋olang又可以支持封裝畦攘、繼承霸妹、多態(tài)這些特性,所以golang到底值不支持面向?qū)ο竽刂海拷?jīng)過多方資料的查閱叹螟,得出如下結(jié)論
- Go支持面向?qū)ο?OOP),并不是純粹的面向?qū)ο笳Z言
- Go沒有類的概念台盯,結(jié)構(gòu)體(struct)相當(dāng)于其它編程語言的類(class)
- Go面向?qū)ο缶幊谭浅:啙嵃照溃ㄟ^接口(interface)關(guān)聯(lián),耦合性低静盅,也非常靈活
接下來咱們就從封裝良价,繼承,多態(tài)三個方面來給大家介紹一下golang的面向?qū)ο蟆?/p>
封裝
一般語言中的面向?qū)ο蠓庋b都類似這樣(偽代碼)
class Person{
name
age
function eat(){
return "eat"
}
}
都是用一個class關(guān)鍵字來定義一個類蒿叠,并且可以自定義他的一些屬性和方法明垢,這種行為咱們也叫做封裝
go語言中是不支持class關(guān)鍵字的,但是可以用struct達(dá)到類似的效果
type Person struct{
name string
age int
}
但是和其他語言不同,struct關(guān)鍵字只能定義屬性栈虚,但是不支持行為袖外,也就是不能定義方法。golang既然支持面向?qū)ο竽敲纯隙ㄊ悄苤С址椒ǖ幕晡瘢徊贿^是寫法稍微有些不同曼验。
golang是通過下面的方式進(jìn)行方法綁定的
func (this *Person) GetName() {
fmt.Printf(this.Name)
}
func main(){
person := Person{
Name: "xiaofan",
Age: 18,
}
person.GetName() //執(zhí)行Person綁定的方法GetName
return
}
其實就是一個簡單的golang函數(shù)泌射,在前面加上(this *Person)就可以實現(xiàn)方法的綁定,其實很多同學(xué)在這里對this不是很理解鬓照,在這里作出如下聲明
(this *Person)
- (this *Person)中的this只是一個變量熔酷,你不用this,寫成(a *Person) 或者(p *Person)也是可以的
- this *Person的含義為 this = *Person,也就是說把結(jié)構(gòu)體Person的指針指向了this
- this *Person中Person必須傳指針類型豺裆,如果寫成(this Person)就相當(dāng)于把Person結(jié)構(gòu)體拷貝了一份給this拒秘,那么this在方法中做任何操作都是和結(jié)構(gòu)體沒有任何關(guān)系的了。
下面是一些在實際中封裝的時候需要注意的地方臭猜,大家可以看看
繼承
我們先來看看其他語言一般是怎么繼承的(偽代碼)
class Person {
name string
function eat(){
print("eat 方法")
}
}
class Student extens Person{ //student類繼承Person類之后就可以用Person類的屬性和方法了
}
但是在go里面繼承的方法比較特殊躺酒,如下
type Person struct {
Name string
Age int
}
func (this *Person) GetName() {
fmt.Printf(this.Name)
}
type Student struct{
Person //這樣Student類就可以繼承Person類了
Score int //student類自己的屬性
}
func main(){
stu := Student{}
stu.Name = "小飯" //繼承父類的屬性
stu.GetName() //繼承父類的方法
return
}
繼承需要注意的地方
權(quán)限控制(大寫)
- 如果一個類需要在包外被使用,則類名首字母大寫
- 如果一個屬性需要被子類使用蔑歌,則首字母大寫
- 如果一個方法需要被子類使用羹应,則首字母大寫
- 首字母大寫,類似于以前給屬性和方法標(biāo)注的public
多態(tài)
多態(tài)是同一個行為具有多個不同表現(xiàn)形式或形態(tài)的能力次屠。
golang中的多態(tài)是通過interface類型實現(xiàn)的
type Person interface { //接口Person規(guī)定了方法GetName
GetName()
}
type Student struct {
Name string
Age int
}
func (this *Student) GetName() {
fmt.Println(this.Name)
}
type Teacher struct {
Name string
Age int
}
func (this *Teacher) GetName() {
fmt.Println(this.Name)
}
- 定義一個接口Person园匹,規(guī)定GetName方法
- Student類和Teacher類都按照Person接口的標(biāo)準(zhǔn)去實現(xiàn)GetName方法
但是我們是否發(fā)現(xiàn)了一個問題,Student和Teacher是按照Person的標(biāo)準(zhǔn)去實現(xiàn)的劫灶,但是從上述代碼看的話裸违,他們互相之間好像沒什么聯(lián)系,所以把類和接口關(guān)聯(lián)的話還得看下面的代碼
func main() {
var stu Person //定義變量為接口類型
stu = &Student{
Name: "小飯",
Age: 123,
}
stu.GetName()
var teacher Person //定義變量為接口類型
teacher = &Teacher{
Name: "老師",
Age: 23,
}
teacher.GetName()
}
- 這個時候在Student和Teacher中實現(xiàn)其他的方法會報錯本昏,因為Person貴定了只能實現(xiàn)GetName方法
當(dāng)然上述方法我們可以稍微改造一下
func GetName(p Person) {
p.GetName()
}
func main() {
stu := Student{
Name: "小飯",
Age: 123,
}
GetName(&stu)
}
這種實現(xiàn)模式被稱為”鴨子類型“供汛,Python 中的接口也是類似的鴨子類型。
總結(jié)
到這里應(yīng)該是能理解官方所說的 Yes and No. 的含義了涌穆;Go 對面向?qū)ο蟮恼Z法不像其他語言 那么嚴(yán)苛紊馏,甚至整個語言中都找不到 object(對象) 這個關(guān)鍵詞;但是利用 Go 里的其他特性也是能實現(xiàn) OOP 的蒲犬。
本文由mdnice多平臺發(fā)布