面向对象——继承
1.嵌套结构体
结构体内的字段有可能也是一个结构体,这样的结构体称为嵌套结构体。
package main
import "fmt"
type Animal struct {
name string
age int
color string
}
type dog struct {
animal Animal
address string
}
func main() {
d := dog{Animal{"wangcai", 10, "white"}, "上海"}
fmt.Printf("d=%+v\n", d)
/*访问嵌入式结构体内部成员,需要显式调用*/
fmt.Printf("name=%s,age=%d,color=%s,address=%s\n", d.animal.name, d.animal.age, d.animal.color, d.address)
var t dog
t.animal.name = "旺财"
t.animal.age = 5
t.animal.color = "白色"
t.address = "北京"
fmt.Printf("t=%+v\n", t)
}
2.匿名组合
如果结构体中的匿名字段是结构体,那么这个结构体所拥有的全部字段都被隐式的引入了当前定义的这个结构体。这种结构体内部嵌套匿名结构体的组合称作匿名组合。而匿名结构体中的成员可以通过外部结构体直接访问。
package main
import "fmt"
type Animal struct {
name string
age int
color string
}
type dog struct {
/*匿名字段,默认dog包含了Animal中的所有字段*/
Animal
address string
}
func main() {
//顺序初始化,成员赋值要一一对应
d1 := dog{Animal{"wangcai", 10, "white"}, "上海"}
fmt.Printf("d1=%+v\n", d1)
fmt.Printf("name=%s,age=%d,color=%s,address=%s\n", d1.name, d1.age, d1.color, d1.address)
//部分初始化
d2 := dog{Animal: Animal{name: "xiaoqiang", color: "blue"}}
fmt.Printf("d2=%+v\n", d2)
var d3 dog
/*匿名字段内部成员直接调用*/
d3.name = "旺财" //等价于d3.Animal.name="旺财"
d3.age = 5
d3.color = "白色"
d3.address = "北京"
fmt.Printf("d3=%+v\n", d3)
}
3.同名字段
外部结构体的成员变量名和嵌入的内部结构体成员变量名相同,则此外部结构体成员被称作同名字段。同名字段,可以通过外部结构体直接访问,但是内部结构体成员变量的访问需要显示调用。
package main
import "fmt"
type Animal struct {
name string
age int
color string
}
type dog struct {
Animal //匿名字段
address string
name string //同名字段
}
func main() {
var d dog
d.name = "旺财" //默认给最外层的 成员赋值
fmt.Printf("d=%+v\n", d)
//给匿名字段内的同名字段赋值,需要显示调用
d.Animal.name = "wangcai"
d.age = 5
d.color = "白色"
d.address = "北京"
fmt.Printf("d=%+v\n", d)
}
4.其他匿名字段
匿名字段不仅可以是结构体类型,还可以是其他任意的内置类型和自定义类型,甚至可以是结构体的指针类型。
4.1 非结构体类型
非结构体类型包括:所有的内置类型和自定义类型。
4.2 结构体指针类型
匿名字段逼近可以是结构体类型,也可以是结构体指针类型
- 非结构体类型
package main
import "fmt"
type Animal struct {
name string
age int
color string
}
type mystr string // 自定义类型
type dog struct {
Animal //匿名字段,结构体类型
string //匿名字段,内置类型
mystr //匿名字段,自定义类型
}
func main() {
d := dog{Animal{"wangcai", 1, "white"}, "上海", "二哈"}
d.mystr = "旺财"
fmt.Printf("d=%+v\n", d)
fmt.Printf("Animal.name=%s,Animal.age=%d,Animal.color=%s,address=%s,name=%s\n", d.name, d.age, d.color, d.string, d.mystr)
}
- 结构体指针类型
package main
import "fmt"
type Animal struct {
name string
age int
color string
}
type dog struct {
*Animal //匿名字段,结构体指针类型
address string
}
func main() {
d := dog{&Animal{"wangcai", 1, "white"}, "上海"}
fmt.Printf("d=%+v\n", d)
fmt.Printf("name=%s,age=%d,color=%s,address=%s\n",
d.name, d.age, d.color, d.address)
var t dog
t.Animal = new(Animal) //分配内存空间
t.name = "旺财"
t.age = 2
t.color = "白色"
t.address = "北京"
fmt.Printf("t=%+v\n", t)
fmt.Printf("name=%s,age=%d,color=%s,address=%s\n", t.name, t.age, t.color, t.address)
}
5.方法的继承与重写
5.1 方法的继承
如果嵌套结构体的内部结构体实现了一个方法,但是外部结构体没有实现这个方法。
如果匿名组合的匿名字段实现了一个方法,那么外部结构体也就实现了这个方法。
5.2 方法的重写
匿名组合的匿名字段实现了一个方法。如果外部结构体对此方法进行了修改,这就叫做方法的重写。
- 方法的继承
package main
import "fmt"
type Animal struct {
name string
age int
color string
}
type dog struct {
//匿名字段,默认dog包含了Animal中的所有字段
Animal
address string
}
func (a *Animal) eat() {
fmt.Println("It likes eat.")
}
func (d *dog) sing() {
fmt.Println("It's singing.")
}
func main() {
d1 := dog{Animal{"wangcai", 10, "white"}, "上海"}
fmt.Printf("d1=%+v\n", d1)
d1.eat()
//继承了方法eat
d1.sing()
}
- 方法的重写
package main
import "fmt"
type Animal struct {
name string
age int
color string
}
type dog struct {
//匿名字段,默认dog包含了Animal中的所有字段
Animal
address string
}
func (a *Animal) eat() {
fmt.Println("It likes eat.")
}
func (d *dog) eat() {
fmt.Println("dog like eat.")
}
func main() {
d1 := dog{Animal{"wangcai", 10, "white"}, "上海"}
fmt.Printf("d1=%+v\n", d1)
d1.eat()
}