Go虽然是面向对象编程,但Go没有函数的继承语法,而是支持给任何类型(不包括指针类型)增加新方法的语法,只需要实现该接口要求的所有方法即可。
直接看以下几个代码例子
//例:给内置类型 int 添加Less方法
type Integer int
func (a Integer) Less(b Integer) bool {
return a < b
}
func (a *Integer) Add(b Integer) {
*a += b
}
func main(){
var a Integer = 1
if a.Less(21) {
fmt.Println(a, "Less 21")
}
a.Add(2); // a=3
}
//自定义结构体
//顺带复习下结构体的初始化
type Rect struct{
x,y float64
width,height float64
}
func (r *Rect) Area() float64{
return r.width * r.height
}
func main(){
r1 := new(Rect)
r2 := &Rect{}
r3 := &Rect{0,0,1,2}
r4 := Rect{ width:1.1, height:2.3 }
r5 := Rect{ x:1.0, y:2.0, width:1.1, height:2.3 }
r1.Area()
r2.Area()
r3.Area()
r4.Area()
r5.Area()
}
虽然Go语言没有继承,但有类似于继承的做法,称为匿名组合;
看代码:
// 代码演示 类似继承 的 匿名组合 语法
type Base struct {
Name string
}
func (base *Base) Foo(){
}
func (base *Base) Bar(){
}
type Foo struct{
Base // 组合
Age int
Addr string
}
func (foo *Foo) Bar(){
foo.Base.Bar() //调用组合结构中的接口
}
func main(){
Foo f
f.Bar()
f.Base.Bar()
//f.Bar() 和 f.Base.Bar() 调用效果完全一致
}
//本例子可以直观演示 匿名组合 的使用技巧
type Job struct{
Command string
*log.Logger //相当于'继承'了log.Logger,可以直接使用log.Logger中的方法
}
func (job *Job) Start(){
job.Log("starting now ...")
// todo
job.Log("started")
}
//对于Job结构的使用者来说,根本不用知道log.Logger类型的存在
//匿名组合中出现同名变量或同名组合者的情况
//1.同名变量
type X struct{
Name string
}
type Y struct{
X // X.Name被隐藏,被外层的Name覆盖
Name string
}
//2.同名组合者
type Logger struct{
Level int
}
type Y struct{
*Logger
Name string
*log.Logger
}// 存在名称都为Logger的组合者
//如果没有使用Logger中的成员,会被忽略冲突,编译不会报错;
//否则会存在二义性错误;