go - 面向对象(2)
go面向对象编程思想-继承
分别定义一个 male 和 female的结构体
type male struct{
name string
height float64
weight float64
sport string
}
func (p *male) test(){
fmt.Println("male 正在上体育课")
}
type female struct{
name string
height float64
weight float64
musical string
}
func (p *female) test(){
fmt.Println("female 正在上音乐课")
}
如上当一个业务需求的两个结构体的字段和方法几乎一模一样,这样会出现几种情况
1、并且却写了几乎相同的代码,代码的复用性不高
2、出现代码冗余,并且代码不利于维护,同时也不利于功能的扩展
那么这个时候我们就可以使用继承这一特性来解决代码复用,使我们的编程更加靠近人的思维
既然 male 和 female 有很多相似的地方,那为什么不能直接 定义一个human这样的一个匿名结构体来实现继承呢
在goalng中为了简便性,就是这样嵌入一个匿名结构体,实际上与其他语言中的父类子类啥的没有什么太多的关系,为了简化结构体之间的关系,也就不存在什么父类子类的说法。
那我们直接定义一个human
package main
import "fmt"
type Human struct{
Name string
Height float64
Weight float64
}//如何想要添加一个方法,是male和female的共同特点,那么就可以直接对human添加一个方法,这样就提高了代码的扩展性
type Male struct{
Human
Sport string
}
type Female struct{
Human
Musical string
}
func (p *Male) SetSport(sport string){
p.Sport = sport
}
func (p *Male) Showinfo(){
fmt.Printf("这个人的名字是%v,身高是%v,体重是%v,运动是%v",p.Name,p.Height,p.Weight,p.Sport)
}
func main(){
p := &Male{}
p.Name = "duan" //这样其实是简写,go会首先查看male是否有这个字段,没有就会从其中的匿名结构体去寻找
p.Height = 188 //完整的写法是 p.Human.Height = 188
p.Weight = 80
p.SetSport("basketball")
p.Showinfo()
}
截下来说一说继承的一些细节
1、结构体可以使用嵌套匿名结构体的所有的字段和方法,无论开头字母是否大小写
2、 当结构体和匿名结构体具有相同字段的时候,那么go就会采取就近原则,但是如果一定要两个都有值的话
那么就需要两个都完整的定义 b.Name = ‘alice’ b.A.Name = “bob” 这样才行
3、 结构体嵌入两个或者多个匿名结构体,如果两个匿名结构体具有相同的字段和方法(同时结构体本身没有相同的字段和方法),那么
在访问的时候就一定要指明匿名结构体的名称(同时这个规则对方法也是一样的),否则就会编译报错
type A struct {
Name string
Age int
}
type B struct {
Name string
Score int
}
type C struct {
A
B
}//这个时候如果想要使用Name属性,那么就一定要指定A还是B,输出的时候也是一样,但是为了代码的简洁性,还是尽量少使用多重继承