Go語言與物件導向編程

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

學習Go語言差不多快兩個月了,感覺這個過程還是蠻快樂的,翻翻英文資料,寫寫小程式,總是覺得有好多東西都搞不明白,一步步走下來,卻發現,這些迷惑好像也是不可或缺的。慢慢思考,最終也找到瞭解決方法,可能不是最好的,但是我會隨著認識的不斷深入,繼續修改。

因為java的東西在我的知識體系中是根深蒂固的,儘管我現在很討厭java體系中的一些東西。對於曾經搞過java的人來說,去學習任何一門新的語言,首先會問,是否是物件導向的語言。剛接觸GO的幾天,曾經帶我的師傅問我go是不是一門物件導向的語言,我閃爍其詞,因為我還沒有搞清楚到底是不是。物件導向思想是一種很好得方法(到目前來說我認為還是這樣)。Go嚴格來說不是一門物件導向的語言,但是,其中的很多方式還是借鑒了物件導向的一些思想,儘管Go更接近C,但是從物件導向這塊,從事java的開發人員還是不陌生的。

物件導向的三大特點:封裝、繼承、多態。

封裝:就我自己的理解而言,封裝就是將某些特徵組裝到一起,其他的對象或類可以使用這個整體,卻不一定能夠知道其實現細節。這又涉及到是否可見的問題。在java中,有privat,public,protected關鍵字來決定訪問的許可權。而在go中,採用了一種算是規定的方法:使用大小寫來確定,大寫是包外可見的,小寫struct或函數只能在包內使用。(go的關鍵字是及其少,簡直可以說是吝嗇,這也是其簡潔的一個原因吧)。Java中,每個class都有其屬性和方法,在go中,沒有class的概念,與C語言一樣,有struct的概念。與C語言不同的是,可以定義只用於這個struct的方法。看個例子會清晰很多。

// lxy project lxy.gopackage lxyimport "strconv"type Student struct {    Name string    Age  int}func (s *Student) SetName(name string) {    s.Name = name}func (s *Student) GetName() string {    return s.Name}func (s *Student) SetAge(age int) {    s.Age = age}func (s *Student) GetAge() int {    return s.Age}func (s *Student) String() string {    return "name is " + s.Name + ",age is " + strconv.Itoa(s.Age)}

先說一下在go中函數定義的格式吧。

func (ptype) funcName(a type)(btype){}

紅色的func是定義函數的關鍵字,是不可變的,綠色部分是可選的,當然,如果有這部分,那就不是個函數了,而是一個方法。這種實現方式相當於是定義了,這個方法只用於這個type的執行個體。紫色部分代表的是函數的傳回值。這個有點奇怪啊。向我們熟悉的語言,不管是java還是C,都會把傳回值放在函數名前邊,go卻把它放到了最後。還有,go中的函數可以有0-n個傳回值,並且可以指定傳回值的名字。

結構體Student封裝了兩個方法,Name和Age,這兩個熟悉包括結構體都是包外可以使用的。然後又給這個結構體定義了幾個方法。看一下在主函數中的調用。

package mainimport (    "fmt"    "lxy")func main() {    ss := new(lxy.Student)    ss.SetName("lxy")    ss.SetAge(20)    fmt.Println(ss.String())}

在go中,要想調用另外一個package中的內容,需要首先import.在go中,所有的都會在一個特定的包中定義或者使用。使用方式為包名.(方法或者全域變數)

繼承:在go中,沒有明確說明繼承的關鍵字,我使用的,我不確定是否是真正意義上的繼承,姑且稱之為類比繼承吧。還是看例子。

package mainimport (    "fmt"    "lxy")type director struct {    lxy.Student    Name string}func (di *director) GetName() string {    fmt.Println("get director name")    return di.Name}func main() {    ss := new(lxy.Student)    ss.SetName("lxy")    ss.SetAge(20)    dd := new(director)    dd.Name = "director"    dd.Student = *ss    fmt.Println(dd.GetName())fmt.Println(dd.Student.GetName())fmt.Println(dd.GetAge())}

還是剛才的代碼,我只是在主函數所在的包中又增加了一個結構體,它包含了Student,而且是匿名包含的,這實際上就是一個繼承。Director的執行個體可以直接調用Student中的所有方法,如最後一條語句。對於一些衝突的處理包括:像本例中,director中包含了GetName方法和Name屬性,與Student中是完全一樣的,因為這個沒有出現在同一個level(何為同一個lever呢?本例中,director中的Name和lxy.Student就是同一個level),所以調用的是level最高的。若是處於同一個level的包含相同的變數名或者方法名,那就必須要明確指明了。比如

type A struct{

 a int

 b string

}

type B struct{

 a int

 c string

}

type C struct{

A

B

}

此時調用var cc C;cc.a 就錯了,因為編譯器不清楚到底是A還是B的a屬性,這個需要指明是cc.A.a還是cc.B.a

多態:這個概念該怎麼說呢,介面的多種不同實現方式。比如一個介面方法:叫。如果貓實現了這個介面,則結果會是“喵喵”;狗實現了這個方法,結果會是“汪汪”…..go中也有介面,只是其實現方式比較奇怪一些,閑話少說,還是拿例子說事:

// lxy project lxy.gopackage lxyimport "strconv"type IPeople interface {    SetName(string)    GetName() string}type Student struct {    Name string    Age  int}type Teacher struct {    Name   string    Course string}func (s *Student) SetName(name string) {    s.Name = name}func (t *Teacher) SetName(name string) {    t.Name = name}func (s *Student) GetName() string {    return s.Name}func (t *Teacher) GetName() string {    return t.Name}func (s *Student) SetAge(age int) {    s.Age = age}func (s *Student) GetAge() int {    return s.Age}func (s *Student) String() string {    return "name is " + s.Name + ",age is " + strconv.Itoa(s.Age)}func (t *Teacher) SetCourse(course string) {    t.Course = course}func (t *Teacher) GetCourse() string {    return t.Course}

代碼中紅色部分定義了一個介面IPeople,其包括兩個方法。上述代碼,我們可以得出一個結論,Teacher和Student都實現了介面IPeople.還沒看出來是吧。因為Teacher和Student都實現了介面IPeople的兩個方法。在go中,不需要顯示聲明某個struct是否聲明了介面,只要其包括介面中的方法,go編譯器就認為這個struct實現了這個介面了。即使介面與這個struct不在同一個包中,也會認為是實現了這個介面。看下主函數中:

package mainimport (    "fmt"    "lxy")type director struct {    lxy.Student    Name string}func (di *director) GetName() string {    fmt.Println("get director name")    return di.Name}func (di *director) SetName(name string) {    di.Name = name}func main() {    ss := new(lxy.Student)    ss.SetName("lxy")    ss.SetAge(20)    dd := new(director)    dd.Name = "director"    dd.Student = *ss    var ii lxy.IPeople    ii = dd    ii.SetName("test")    fmt.Println(ii.GetName())}

一個struct可以實現多個介面,一個介面也可以被多個struct實現,這些與大家熟知的物件導向語言相同。介面在go語言中是很重要的一種結構,其意義遠比在java中深遠。具體的大家可以參考下go的學習資料。

 

差不多吧,我想到且知道的就是這些,雖然不是嚴格意義上的物件導向,但是最起碼做到了神似。




相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.