在GO结构体类型中嵌套一个其他的类型可以到达继承的目的。
语法:
struct {
T | *T
}
A field or method f
of an anonymous field in a struct x
is called promoted if x.f
is a legal selector that denotes that field or method f
.
Promoted fields act like ordinary fields of a struct except that they cannot be used as field names in composite literals of the struct.
Given a struct type S
and a type named T
, promoted methods are included in the method set of the struct as follows:
//main.go
package main
import "fmt"
type Father struct { //父类
name string
age int
}
func (f Father) Speek(x string) { //父类Speek方法
fmt.Println(x)
}
func (f *Father) Grow() { //父类Grow方法
f.age += 1
}
type Child struct { //子类
Father //类型组合
height float32
}
func main() {
var f = Father{name: "zlf", age: 30}
var c = Child{Father: f, height: 170} //由于c.Father类型是值类型,所以将f赋值给c.Father时,会发生值拷贝过程
c.Speek("Hello World") //子类对象直接调用父类的Speek方法
fmt.Println(c)
c.Grow() //子类对象调用父类的Grow方法,但是Grow方法的接收器是c.Father,而不是c,更不是f
fmt.Println("c = ", c)
fmt.Println("f = ", f)
}
C:/go/bin/go.exe run test5.go [E:/project/go/proj/src/test]
Hello World
{{zlf 30} 170}
c = {{zlf 31} 170}
f = {zlf 30}
成功: 进程退出代码 0.
example2:嵌套类型Father,查看子类型Child的方法集
//main.go
package main
import "fmt"
type Father struct { //父类
name string
age int
}
func (f Father) Speek(x string) { //父类Speek方法
fmt.Println(x)
}
func (f Father) Grow() { //父类Grow方法
f.age += 1
}
type Child struct { //子类
Father //类型组合
height float32
}
type SpeekGrower interface {
Speek(x string)
Grow()
}
func main() {
var f = Father{name: "zlf", age: 30}
var c = Child{Father: f, height: 170} //由于c.Father类型是值类型,所以将f赋值给c.Father时,会发生值拷贝过程
var sg SpeekGrower
sg = c //类型CHILD
sg.Speek("This is a test.")
sg = &c //类型*CHILD
sg.Speek("This is a test.")
}
编译运行:
C:/go/bin/go.exe run test7.go [E:/project/go/proj/src/test]
This is a test.
This is a test.
成功: 进程退出代码 0.
//main.go
//main.go
package main
import "fmt"
type Father struct { //父类
name string
age int
}
func (f Father) Speek(x string) { //父类Speek方法
fmt.Println(x)
}
func (f *Father) Grow() { //父类Grow方法
f.age += 1
}
type Child struct { //子类
Father //类型组合
height float32
}
type SpeekGrower interface {
Speek(x string)
Grow()
}
func main() {
var f = Father{name: "zlf", age: 30}
var c = Child{Father: f, height: 170} //由于c.Father类型是值类型,所以将f赋值给c.Father时,会发生值拷贝过程
var sg SpeekGrower
sg = c //因为c类型是Child,值类型,赋值给接口时,会发生值拷贝,所以,该操作成功的前提是Child的所有方法都必须是值接收器
sg.Speek("This is a test.")
sg = &c
sg.Speek("This is a test.")
}编译运行:
C:/go/bin/go.exe run test7.go [E:/project/go/proj/src/test]
# command-line-arguments
.\test7.go:32: cannot use c (type Child) as type SpeekGrower in assignment:
Child does not implement SpeekGrower (Grow method has pointer receiver)
错误: 进程退出代码 2.
总结:通过上面两个例子,可以看出,当嵌套类型是Father时,类型Child的方法集只包括Father中接收器为值的方法;类型*Child的方法集包含了Father中所有的方法,所以*Child实现了上述的接口。
//main.go
package main
import "fmt"
type Father struct { //父类
name string
age int
}
func (f Father) Speek(x string) { //父类Speek方法
fmt.Println(x)
}
func (f *Father) Grow() { //父类Grow方法
f.age += 1
}
type Child struct { //子类
*Father //类型组合
height float32
}
type SpeekGrower interface {
Speek(x string)
Grow()
}
func main() {
var f = Father{name: "zlf", age: 30}
var c = Child{Father: &f, height: 170}
var sg SpeekGrower
sg = c //类型Child,这里会发生值拷贝
sg.Speek("This is a test.")
sg = &c //类型*Child,这里会发生引用传递
sg.Speek("This is a test.")
}编译运行:
C:/go/bin/go.exe run test7.go [E:/project/go/proj/src/test]
This is a test.
This is a test.
成功: 进程退出代码 0.