1.1.1. 一、继承的实现:
在go语言中,继承是通过嵌套匿名结构体实现的。示例如下:
// 父结构体
type Father struct {
Name string
age int
}
// 子结构体
type Son struct {
Father
grade string // 年级
}
说明:
在子结构体定义时,在内部放一个父机构体即可实现继承。
1.1.2. 二、完整的使用如下:
// 父结构体
type Father struct {
Name string
age int
}
// 子结构体
type Son struct {
Father
grade string // 年级
}
func main() {
son := &Son{}
// 1、通过Father给父结构体的属性赋值
son.Father.age = 40
son.Father.Name = "父亲"
son.grade = "6年级"
fmt.Println(son) // &{ {父亲 40} 6年级}
son2 := &Son{}
// 2、直接给Father的属性赋值
son2.age = 40
son2.Name = "son2父亲"
son2.grade = "3年级"
fmt.Println(son2) //&{ {son2父亲 40} 3年级}
}
说明:给父机构体的属性赋值,或查询父机构体的属性值。有2种方式:
通过父结构体的属性赋值。如:son.Father.age = 40。
直接赋值。如:son2.age = 40。
1.1.3. 三、子结构体访问父结构体属性的访问原则。
关于父结构体、子结构体属性的访问和修改。有下面几个原则:
- 结构体可以使用嵌套匿名结构体(父结构体)所有的字段和方法,即:首字母大写或者小写的字段、方法, 都可以使用。
- 不通过父结构体,直接给属性赋值时(son2.age = 40)。编译器会先看Son 中有没有 age, 如果有,则直接赋值给Son中的age。
- 如果没有就去看 Son 中嵌入的匿名结构体Father 有没有声明 age 字段,如果有就赋值给Father的age,如果没有继续查找Son 中嵌入的其他匿名结构体(多重继承),如果都找不到就报错。
- 当结构体和其内部嵌入的匿名结构体有相同的字段或者方法时,编译器采用就近访问原则访问,如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分。
- 结构体嵌入两个(或多个)匿名结构体,如两个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),在访问时,就必须明确指定匿名结构体名字,否则编译报错。
- 如果一个 struct 嵌套了一个有名字的结构体,这种模式就是组合,如果是组合关系,那么在访问组合的结构体的字段或方法时,必须带上结构体的名字。
嵌套有名字的结构体(组合模式),赋值时必须指明结构体名字,示例如下:
// 父结构体
type Father struct {
Name string
age int
}
// 子结构体
type Son struct {
fa Father
grade string // 年级
}
func main() {
son := &Son{}
// 嵌套有名字的结构体(组合模式),赋值时必须指明结构体名字
son.fa.age = 40
son.fa.Name = "父亲"
son.grade = "6年级"
fmt.Println(son) // &{ {父亲 40} 6年级}
}
注意:组合模式就不是继承了。嵌套匿名结构体才是继承。
7、可以在创建子结构体的示例时,直接指定各个匿名结构体(父结构体)字段的值。
// 父结构体
type Father struct {
Name string
age int
}
// 子结构体
type Son struct {
Father
grade string // 年级
}
func main() {
// 指定父结构体的属性值
son := &Son{Father:Father{Name:"父",age:45},grade:"1年级"}
fmt.Println(son) // &{ {父 45} 1年级}
}
8、嵌套结构体时,可以嵌套指针。效率更高。
// 父结构体
type Father struct {
Name string
age int
}
// 子结构体
type Son struct {
*Father //嵌套指针
grade string
}
func main() {
// 指定父结构体的属性值
son := &Son{
Father:&Father{Name:"父",age:45},
grade:"1年级",
}
fmt.Println(son) // &{0xc00005a420 1年级}
fmt.Println(*son.Father) //{父 45}
}
9、嵌套基本类型。访问的时候直接访问。如:son.float64 = 100。
// 子结构体
type Son struct {
grade string
int // 基本类型嵌套
float64 // 基本类型嵌套
}
func main() {
son := &Son{
grade:"1年级",
int:6,
}
son.float64 = 100
fmt.Println(son.int) // 6
fmt.Println(son.float64) // 100
}
嵌套基本类型,实际上字段的名字就是基本类型的名字。如int、float64 。如果嵌入2个相同的类型,就会报错。如下:
type Son struct { grade string int // 基本类型嵌套 int // 报错 }
10、多重继承:其实就是子结构体中嵌入多个匿名结构体。(不推荐使用)
// 父1
type Father1 struct {
Name string
age int
}
// 父2
type Father2 struct {
Name string
age int
}
// 子
type Son struct {
*Father1
*Father2
}