从测试中分析Go语言中的"继承"

2023-10-13 22:56:08 浏览数 (1)

前言

本文是探讨的是"go语言中的“继承”"

此文章是个人学习归纳的心得, 为掘金首发 , 如有不对, 还望指正, 感谢!

判断是否有阅读本文的必要,可以先看下面的样例

样例一

代码语言:go复制
package main

type student struct {
     name string
     id   int
     age  int
}

func (s student) getName() string {
     return s.name
}


type schoolOne struct {
     student
}

type schoolTow struct {
     s student
}

请问schoolOne和schoolTow有什么区别? 在调用getName方法上,有什么区别?

答案

schoolOne和schoolTow都是嵌入了结构体student,但是schoolOne是隐式嵌入,schoolTow是显示嵌入,给这个结构体重命名为s,

隐式嵌入会实现go的自动转发,类似于其他语言的继承,就是说schoolOne得到了student的getName方法。

go语言作为一门极简的语言,是没有类一说的,但是go通过结构体和转发实现了类似类和继承的效果。

在调用上的区别:

代码语言:txt复制
func main() {
   One := &schoolOne{struct {
      name string
      id   int
      age  int
   }{name: "言志志", id: 666, age: 18}}

   Tow := &schoolTow{struct {
      name string
      id   int
      age  int
   }{name: "言志志2", id: 999, age: 18}}

   fmt.Printf("%v", One.getName())
   fmt.Printf("%v", Tow.s.getName())
   fmt.Printf("%v", One.student6.getName())  //还可以这样
}

其实就是说,如果是隐式的话,就会比较方便,因为你没有给定字段名,显式的话,要通过字段名来调用。

代码语言:txt复制
fmt.Printf("%v", Tow.student6.getName())  会报错

报错是因为,你已经给了字段名了,这个隐式的转发,也就是go的自动转发。

关于字段的自动转发的测试

属性也会自动转发

代码语言:txt复制
package main

import "fmt"

type student struct {
   name string
   id   int
   age  int
}

func (s student) getName() string {
   return s.name
}

type schoolOne struct {
   student
}
func main() {
   One := &schoolOne{struct {
      name string
      id   int
      age  int
   }{name: "言志志", id: 666, age: 18}}

   fmt.Printf("%v", One.id)
}

运行结果:

但是需要注意的,这个字段的首字母,我用的小写,所以只能在包内可以这样,其他包引用的话,即使是转发了,但是由于没有公开,你还是看不到效果的

父结构体和嵌入的子结构体重名

代码语言:txt复制
package main

import "fmt"

type student struct {
   name string
   id   int
   age  int
}

func (s student) getName() string {
   return s.name
}

type schoolOne struct {
   name string
   student
}

func (s schoolOne) getName() string {
   return s.name
}

func main() {
   One := &schoolOne{"言志志1号", struct {
      name string
      id   int
      age  int
   }{name: "言志志2号", id: 666, age: 18}}

   fmt.Printf("One.name:%v n", One.name)
   fmt.Printf("One.student6.name: %v n", One.student6.name)

   fmt.Printf("One.getName(): %v n", One.getName())
   fmt.Printf("One.student6.getName(): %v n", One.student6.getName())
}

运行结果如下:

就是如果重名的话,会先考虑父结构体里面的,要调用子结构体里面的,就是要用结构体名来调用

但是没有重名的就仍然会继承到那个父结构体上面,还是可以像之前一样调用。

我正在参与2023腾讯技术创作特训营第二期有奖征文,瓜分万元奖池和键盘手表

0 人点赞