基本概念
对于面向对象编程的支持 Go 语言设计得非常简洁而优雅。因为, Go 语言并没有沿袭传统面问对象编程中的诸多概念,比如继承(不支持继承,尽管匿名字段的内存布局和行为类似继承,但它并不是继承)、虚函数、构造所数和析构函数、隐藏的 this 指针等。
尽管 Go 语言中没有封装、继承、多态这些概念,但同样通过别的方式实现这些特性:
- 封装:通过方法实现
- 继承:通过匿名字段实现
- 多态:通过接口实现
匿名组合
匿名字段
一般情况下,定义结构体的时候是字段名与其类型一一对应,实际上 Go 支持只提供类型而不写字段名的方式,也就是匿名字段,也称为嵌入字段。
当匿名字段也是一个结构体的时候,那么这个结构体所拥有的全部字段都被隐式地引入了当前定义的这个结构体。
- 相当于student结构体里面,继承了person里面的成员。
- 也可以对不是结构体的成员使用匿名字段,但是没有什么意义
初始化
操作成员
与普通结构体成员操作是一样的。
也可以单个赋值,操作等。
同名字段
如果能在本作用域找到此成员,就操作此成员,没有找不到就找继承的字段
- 可以进行显示调用
结构体指针的匿名字段
- 可以直接对其进行初始化
- 也可以先分配空间,然后进行初始化。
方法
在面向对象编程中,一个对象其实也就是一个简单的值或者一个变量,在这个对象中会包含一些函数,这种带有接收者的函数,我们称为方法(method)。本质上,一个方法则是一个和特殊类型关联的函数。
一个面向对象的程序会用方法来表达其属性和对应的操作,这样使用这个对象的用户就不需要直接去操作对象,而是借助方法来做这些事情。
在 Go语言中,可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法。
语法
方法总是绑定对象实例,并隐式将实例作为第一实参(receiver),方法的语法如下:
func (receiver ReceiverType)funcName (parameters)(results)
- 参数 receiver 可任意命名。如方法中未曾使用,可省略参数名。
- 参数 receiver 类型可以是 T或 *T。基类型 T 不能是接口或指针。
- 不支持重载方法,也就是说,不能定义名字相同但是不同参数的方法。
- a相当于就是我们传入的一个参数了即为tmp;
a.
然后调用方法,传入另一个参数,也就是other。
为结构体类型添加方法
- 只要接收者类型不一样,即使方法同名,也属于不同的方法,不会出现重复定义函数的错误
值语义和引用语义
值语义–就是值传递
引用语义–地址传递
方法集
类型的方法集是指可以被该类型的值调用的所有方法的集合。
用实例 value 和 pointer 调用方法(含匿名字段)不受方法集约束,编详器编总是查找全部方法,并自动转换 receiver 实参。
指针变量的方法集
结构体变量是一个指针变量,它能够调用哪些方法,这些方法就是一个集合,简称方法集。
一个指向自定义类型的值的指针,它的方法集由该类型定义的所有方法组成,无论这些方法接受的是一个值还是一个指针。
如果在指针上调用一个接受值的方法,Go语言会将该指针解引用,并将指针所指的底层值作为方法的接收者。
普通变量的方法集
编详器编总是查找全部方法,并自动转换 receiver 实参。
方法的继承
如果匿名字段实现了一个方法,那么包含这个匿名字段的结构体struct也能调用该匿名字段实现的方法。
方法的重写
当继承的类,也重写了继承类实现的方法,在调用的时候也是本着就近原则,先找本作用域的方法,找不到再使用继承的方法。
如果想使用继承的方法,就需要进行显示调用
方法值
保存方法的入口地址