1、結構體方法
go不是純粹的面向對象的,在go里面函數是一等公民,但是go也有結構體實現類似java一樣類的功能來提供抽象。結構體的方法分為值方法和指針方法,前者在方法中做的改變不會改變調用的實例對象,后者則會改變,同樣不管是值類型還是指針類型都是可以被調用的,因為go結構體底層會自動轉化
比如下面是正常的調用:
type Stu struct {
name string
}
func (this Stu) SayName() {
log.Println(this.name)
}
s:=Stu{"Biningo"}
s.SayName()
如果再定義一個方法
func (this *Stu) ChangeName(name string) {
this.name = name
}
因為要改變,所以定義了一個指針類型方法,但是如下調用還是可以的
s:=Stu{"Biningo"}
s.ChangeName("xxx") // 會改變
s2:=&Stu{"Biningo"}
s2.ChangeName("xxxx") //會改變
s2.SayName() //會默認轉化 相當於(*s2).SayName() xxxx
注意,go中是不允許方法重載的。同時不管是值類型方法還是指針類型方法名字也不允許一樣
2、匿名屬性和繼承
繼承:
type Camera struct {
name string
}
type Phone struct{}
func (p *Phone) Call() {
fmt.Println("打電話")
}
func (c *Camera) TakePicture() {
fmt.Println("拍照片")
}
type CameraPhone struct {
Camera
Phone
}
繼承只需要結構體內嵌一個要繼承的結構體就可以了,這樣就可以直接使用父類的方法了
phone:=new(CameraPhone)
phone.Call()
phone.TakePicture()
匿名屬性:
type CameraPhone struct {
Camera
Phone
int
}
我們加了一個int類型,這時候相當於加了一個名字為int,類型為int的屬性,名字和類型名一樣
可以如下使用:
phone:=new(CameraPhone)
phone.Call()
phone.TakePicture()
phone.int=1001
但是注意,匿名屬性同類型只允許一個
那么我們允不允許繼承組合一個借口類型呢?那當然也是可以的
下面看一種結構體和接口的組合並且實現多態:
type Clothe interface {
SayColor()
}
type BlueClothe struct {
Color string
}
func (b *BlueClothe) SayColor() {
log.Println("Blue")
}
type RedClothe struct {
Color string
}
func (b *RedClothe) SayColor() {
log.Println("Blue")
}
type Stu struct {
Clothe
Name string
}
func main() {
blue:=&BlueClothe{Color:"Blue"}
var stu Stu
stu.Clothe = blue //匿名類型名字就是類型名
stu.Name="biningo"
stu.SayColor()
}
3、結構體屬性名稱沖突
既然可以隨意繼承組合,並且可以直接由子類調用,那如果繼承多個父類有相同的屬性名怎么區分呢?如下:
type A struct {
a,b int
}
type B struct {
a int
}
上面定義了兩個結構體,下面繼承這兩個結構體,注意這里a屬性名字相同
type C struct {A;B}
如下解決沖突
c:=C{A{1,1},B{2}}
fmt.Println(c.A.a,c.B.a) //c.a報錯 需要指明是A還是B的a
還記得匿名字段吧,這里就相當於點出具體屬性,調用具體屬性的屬性
一般匿名字段的方法是可以直接調用的,匿名字段名調用方法的時候是可以忽略字段名的,相當於是一個縮寫形式
但是如果兩個沖突字段深度不一樣呢?那就是淺的覆蓋深的屬性