淺談GO語言中的面向?qū)ο髮崿F(xiàn)

人有的時候真的很賤,忙的時候想閑下來,閑的時候又很懷念忙的日子。疫情的這段時間待在家里遠程辦公,晚上空閑的時間相對較多,突然有種想學習一門新語言的沖動,選擇什么好呢?記得年前出差的產(chǎn)品部兄弟告訴我,年后他想學習一下go語言,不糾結,擼起袖子搞搞看。鼓搗了一周多,發(fā)現(xiàn)這個語言真有特點,這里談談go的面向?qū)ο髮崿F(xiàn)的奇特感受。

什么是面向?qū)ο?,滿足三大特性,封裝、繼承和多態(tài)。嚴格來講,go語言是沒有面向?qū)ο螅拖駝討B(tài)語言的世界里一直流傳著一種叫做鴨子類型的風格,“如果它走起來像鴨子,叫起來像鴨子,那它就是一只鴨子”,golang就是這樣的,沒有類,只有struct,且struct只擁有變量,不能帶有method,只能通過struct+method的巧妙方式去實現(xiàn),使其看起來具備OOP風格的“鴨子”。

  1. 封裝和繼承
    封裝從字面上來理解就是包裝的意思,專業(yè)點就是信息隱藏,圈內(nèi)的行話就是封裝屬性和方法。繼承就是子類繼承父類的的屬性和方法,比較好理解。go語言里面的封裝和繼承,通過另外一種方式實現(xiàn),比較奇特,來一段代碼看看。
package main
import (
   "fmt"
)

/*
Person結構體當成類
屬性:age name
方法:setName getName setAge printInfo
是不是有點奇怪和變態(tài) struct+method
 */
type Person struct {
   age int
   name string
}

func (this *Person)setName(tName string){
   this.name=tName
}
func (this *Person)getName()(string){
   return this.name
}
func (this *Person)setAge(tAge int){
   this.age=tAge
}
func (this *Person)printInfo(){
   fmt.Printf("Hello,my name is  %s,I'm %d years old.\n",this.name,this.age);
}

/*
1.Student繼承Person同時擁有 Person下的所有的函數(shù)etName getName setAge printInfo
2.同時重載printInfo方法
*/
type Student struct {
   Person
   grad int
   class int
}
func (s *Student)printInfo(){
   fmt.Printf("Hello,I'm a student,my name is  %s,I'm %d years old,I'm in class %d, grad %d .\n",s.name,s.age,s.class,s.grad);
}

func main(){
   p:=Person{36,"Ap" }
   p.printInfo()

   p.setName("Yuki")
   p.setAge(7)
   p.printInfo()

   s:=Student{p,1,3}
   s.printInfo()

   s.setName("Tom")
   s.setAge(12)
   s.printInfo()
}
##########go run main.go##########
Hello,my name is  Ap,I'm 36 years old.
Hello,my name is  Youki,I'm 7 years old.
Hello,I'm a student,my name is  Yuki,I'm 7 years old,I'm in class 3, grad 1 .
Hello,I'm a student,my name is  Tom,I'm 12 years old,I'm in class 3, grad 1 .

  1. 多態(tài)
    go沒有 implements, extends 關鍵字,嚴格來說,多態(tài)與繼承、重載并不是孤立的,它們之間存在著緊密的聯(lián)系。在百度百科中的多態(tài)解釋,“在面向?qū)ο笳Z言中,接口的多種不同的實現(xiàn)方式即為多態(tài)。引用Charlie Calverts對多態(tài)的描述——多態(tài)性是允許你將父對象設置成為一個或更多的他的子對象相等的技術,賦值之后,父對象就可以根據(jù)當前賦值給它的子對象的特性以不同的方式運作;java中當子類擁有和父類同樣的函數(shù),當通過這個父類對象的引用調(diào)用這個函數(shù)的時候,調(diào)用到的是子類中的函數(shù)”(哇,好復雜!好繞口!),能不能簡單化一點,我的理解是,同一個函數(shù)定義接受為父類,調(diào)用時為子類的實例而執(zhí)行傳入實例下的動作。菜鳥教程解釋為,同一個接口,使用不同的實例而執(zhí)行不同操作(還是菜鳥說得好?。?。直接擼代碼,如下:
package main
import (
   "fmt"
)

//相當于父類或者超類
type Human interface{
   HelloWord()
}

func printfHello(h Human){
   h.HelloWord()
}

//Student實現(xiàn)了Human的HellWord
type Student struct {
   name string
}
func (s *Student)HelloWord(){
   fmt.Printf("Hello ,I'm a student,my Name is  %s.\n",s.name);
}

//Man實現(xiàn)了Human的HellWord
type Man struct {
   name string
}
func (s *Man)HelloWord(){
   fmt.Printf("Hello ,I'm a workman,my Name is  %s.\n",s.name);
}

func main(){
   s:=&Student{"Yuki"}
   m:=&Man{"Ap"}
   
   //多態(tài)
   printfHello(s)
   printfHello(m)
}

######go run main.go########
Hello ,I'm a student,my Name is  Yuki.
Hello ,I'm a workman,my Name is  Ap.

Human 是個接口,這里可以理解為其它語言中的父類,用interface來模仿superclass。 Student和Man實現(xiàn)了HelloWord方法,但是Human 怎么知道Student和Man已經(jīng)實現(xiàn)了它呢? 原因在于Student、Man實現(xiàn)了Human 中的全部方法, 這個時候就會認為子類。

golang社區(qū)很多數(shù)人認為,少了其它語言的implements/extends,讓go顯得更加優(yōu)雅。但是如果沒有implements 關鍵字,怎么知道m(xù)an和student,實現(xiàn)了human的接口,如果沒有文檔,又不熟悉接口類庫的話,感覺程序維護代碼的工作量會加重很多,優(yōu)雅從何談起呢?

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容