這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
GO語言為我們提供了輕量級的物件導向模式,但是不同於JAVA和C++,沒有繼承這個概念,甚至找不到構造(構析)函數的影子,相對於重量級的物件導向語言,GO語言的物件導向似乎更像硬是用C語言的指標來實現OO。
首先,介紹一下最基本的對象聲明,和C語言極為類似:
type object struct { some_var int other_var string}
裡面的變數還可以用指標:
type man struct { name string id int}var woman struct { name string id int husband *man}
type some_object struct 與 var some_object struct是等效的,但是根據$go/doc/GoCourseDay2.pdf中的描述前者更常用。
請注意這個是結構體,裡面只能放變數!想要實作類別似java中的SomeObject.doSomething()一類的事情得用其他方法,這種試圖在結構體內定義函數的方法是錯誤的:
type worry_object struct { some_var int some_var string func some_method(i *int) int{ return 100 }}
然後就是使用聲明好的結構體了,GO語言提供了new()函數,注意是內建函數不是關鍵字,這意味著使用new()函數,你得到將是一個指向該結構體的指標:
func main(){bro_chun := new(man)//故意用很不明確的聲明方式bro_chun.name = "Li_Yuchun"bro_chun.id = 666fmt.Println("bro_chun name is:" + bro_chun.name)fmt.Print("bro_chun id is:")fmt.Println(bro_chun.id)fmt.Print("what is this?")fmt.Println(bro_chun)//注意這行輸出}
輸出:
bro_chun name is:Li_Yuchunbro_chun id is:666what is this?&{Li_Yuchun 666}//看見了沒?是帶&的
GO語言還有可以將聲明和定義變數放在一起的方式:
bro_zeng := &man{"Zeng_Yike",21}fmt.Println(bro_zeng)output:&{Zeng_Yike 21}
對象的方法:必須理解GO語言中方法與物件導向的關係,GO語言中的方法不在結構體中聲明,而是像一個函數一樣寫在外部,並且在函數前面加上指向這個結構體的指標就算是完成綁定了,然後就可以利用這個綁定的指標使用結構體裡的變數了。
首先熟悉一下GO語言中的函數:
func some_func(s string) string { return "lalala~" + s}
func是聲明函數關鍵字,小括弧裡面寫輸入參數,可以這樣寫來輸入同類型的參數(i,j int),後面接的是傳回值,上面這個函數傳回值是string類型。我們要給前面的man類型的結構體準備一個方法say()來說出自己的名字:
func say() string {return "i cant say my name!"
man還不能說自己的名字,下面我們將這個函數綁定為man的方法:
func (m *man) say() string {return "my name is" + m.name}
僅僅是在函數前面加上要綁定對象的結構體的引用,就可以在函數體中使用了,還有一種方式就是把前面小括弧裡面的*man換成man,這種方法類似於java的靜態方法,由結構體提供某些方法(內部實現與靜態方法不同),你不能用這種方法來改變結構體內部變數的值:
package mainimport "fmt"type man struct {name stringid int}func (m *man) change_id(id int){m.id = id}func (m man) change_id2(id int){m.id = id}func main(){m := &man{"nobody",100}m.change_id(50)fmt.Println(m.id)m2 := &man{"somebody",200}m2.change_id2(150)fmt.Println(m2.id)
output:
50
200
第二種改變id的方法是無效的。
介面:這個介面從意義上來說幾乎和JAVA是一樣的,就是一個或多個方法的集合,GO語言的不同是可以有空介面——能夠指向一切類型。介面的聲明文法是這樣的:
type animal interface {Say()Run()}
剩下的事情就不用管,只管像上面一樣Binder 方法,而且可以將一種方法綁定到兩種對象上去,實現多態:
type cat struct {name string}type dog struct {name string}func (c *cat) Say(){fmt.Println("miao~miao~" + c.name)}func (d *dog) Say(){fmt.Println("wang!wang!" + d.name)}func (c *cat) Run(){fmt.Println("wu~~~~~~!")}func (d *dog) Run(){fmt.Println("ao~~~~~~!")}func main(){c := &cat{"jiafei"}d := &dog{"putty"}c.Say()d.Say()c.Run()d.Run()}
讓cat和dog綁定了animal介面中所有的方法,cat和dog類就實現了anmial介面
output:miao~miao~jiafeiwang!wang!puttywu~~~~~~!ao~~~~~~!
我們就可以使用animal這個介面作為指向cat或者dog類的指標了:
var a1,a2 animal //注意,這是聲明的就是指標類型,不要寫成*animala1 = ca2 = da1.Run()a2.Run()output:wu~~~~~~!ao~~~~~~!
然後我們在其他地方調用以介面作為輸入參數的函數時候靈活性就能大大提升了~哦也!頭一次寫部落格,板磚來吧!