GO學習筆記——組合(18)

GO只支持封裝,不支持繼承,那麼如果我們想要對其他包上的一些類型進行擴展,比如說在原有結構體上加上一些自己的東西,C++中可以用繼承實現,但是GO沒有,所以GO引入了組合,用組合來實現繼承的功能,同樣起到代碼複用的效果。

如果我們想在本包中使用別的包中的類型,但又不想使用它的名字,使用別名就可以搞定。

如果想要在本包中使用別的包中的類型,同時想在此基礎上,添加一些功能和內容,就可以使用組合,下面來講組合。


這邊爲了方便演示,就在同一個包中演示了。

//父結構體,表示人
type person struct{
	name string
	age int
}

//子結構體,繼承父類的屬性,同時還有別的屬性
type student struct {
	person	//這部分只放一個person,那麼這裏就是一個匿名變量
	class string
	sno string
}


func main() {
	a := student{person:person{name:"pigff",age:21},class:"計本154",sno:"12345678"}
	fmt.Println(a.name)
}

輸出結果

pigff

如上代碼,定義了一個person結構體表示人,它有字段name和age,再定義了一個student結構體,它裏面有一個匿名字段,該字段類型是person(該字段名默認和類型名一樣,這一點可以在main函數的賦值語句看到,還有自己的字段class和sno。這樣的結構體類型就起到了繼承的效果,student結構體繼承了person結構體的所有字段name和age,因爲我們將該字段定義成了匿名字段,因此,我們可以直接打印 (a.name),直接訪問到person結構體中的字段

 

如果不定義成匿名字段會怎樣,來上代碼

//父結構體,表示人
type person struct{
	name string
	age int
}

//子結構體,繼承父類的屬性,同時還有別的屬性
type student struct {
	basic person	//這部分只放一個person,那麼這裏就是一個匿名變量
	class string
	sno string
}


func main() {
	a := student{basic:person{name:"pigff",age:21},class:"計本154",sno:"12345678"}
	fmt.Println(a.name)
}

我們在student結構體中定義了一個person類型的變量的basic,因此我們下面在賦值的時候也是用的basic。但是這樣的程序會出錯

.\main.go:21:15: a.name undefined (type student has no field or method name)

a中沒有字段名叫name,也就是說,我們不能直接訪問我們繼承下來的父結構體的字段。

所以,如果想要訪問原有類型的字段,那麼就需要在結構體中將該類型定義成匿名字段(通常都是定義成匿名字段的)。

這兩個結構體不是繼承的關係,是組合,但是它起到了繼承的效果,也有繼承最關鍵的作用——代碼複用。

 

另外還要說一點:如果要組合的原類型很大,那麼在組合類型中最好將該字段定義成指針類型,這樣可以節省空間。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章