欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

go结构体继承组合和匿名字段

程序员文章站 2022-07-06 12:51:27
1、结构体方法 go不是纯粹的面向对象的,在go里面函数是一等公民,但是go也有结构体实现类似java一样类的功能来提供抽象。结构体的方法分为 值方法 和 指针方法 ,前者在方法中做的改变不会改变调用的实例对象,后者则会改变,同样不管是值类型还是指针类型都是可以被调用的,因为go结构体底层会自动转化 ......

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 

还记得匿名字段吧,这里就相当于点出具体属性,调用具体属性的属性

一般匿名字段的方法是可以直接调用的,匿名字段名调用方法的时候是可以忽略字段名的,相当于是一个缩写形式

但是如果两个冲突字段深度不一样呢?那就是浅的覆盖深的属性