Go继承的方法重写,继承抽象类实现
go的接口和继承就没什么好说的了,基本上大家都知道怎么玩,这里说下可能会困扰大家的问题。在Java里方法的重写和抽象类是很好用的,对于抽象和尽量共用抽象出来的代码很重要,但是用go很多人又不知道该怎么写才好,所以这里说下在go里怎么实现
方法重写
func main() {
m := &Man{}
m.Eat()
m.Run()
m.Sleep()
}
type Person struct {
}
func (this *Person) Eat() {
fmt.Println("Person Eat")
}
func (this *Person) Run() {
fmt.Println("Person Run")
}
func (this *Person) Sleep() {
fmt.Println("Person Sleep")
}
type Man struct {
Person
}
func (this *Man) Eat() {
// 类似于Java的 super.Eat()
this.Person.Eat()
fmt.Println("Man Eat")
}
func (this *Man) Run() {
fmt.Println("Man Run")
}
运行结果:
Person Eat
Man Eat
Man Run
Person Sleep
这里重写了Eat方法,但是里面通过显示调用父类的Eat方法模拟出Java的super.xxx的效果,所以先打印Person eat,然后打印Man Eat
然后重写了Run方法,所以覆盖掉了父类的Run方法,打印出Man Run
最后因为Man没有实现Sleep方法,所以调用Man的Sleep方法其实是调用的父类Person的实现,打印出Person Sleep
抽象类
抽象类困扰了我很长时间,后来在c语言的很多项目里面找到了答案,那就是使用函数指针
func main() {
akita := NewAkita()
akita.Eat()
labrador := NewLabrador()
labrador.Eat()
}
type AbstractDog struct {
Sleep func()
}
func (this *AbstractDog) Eat() {
fmt.Println("AbstractDog Eat")
this.Sleep()
}
func (this *AbstractDog) Run() {
fmt.Println("AbstractDog Run")
}
// 秋田犬
type Akita struct {
AbstractDog
}
func NewAkita() *Akita {
ptr := &Akita{}
ptr.AbstractDog.Sleep = ptr.Sleep
return ptr
}
func (this *Akita) Sleep() {
fmt.Println("Akita Sleep")
}
// 拉布拉多犬
type Labrador struct {
AbstractDog
}
func NewLabrador() *Labrador {
ptr := &Labrador{}
ptr.AbstractDog.Sleep = ptr.Sleep
return ptr
}
func (this *Labrador) Sleep() {
fmt.Println("Labrador Sleep")
}
运行结果:
AbstractDog Eat
Akita Sleep
AbstractDog Eat
Labrador Sleep
这里关键的意思是秋田和拉布拉多共享了eat方法的实现,也许eat方法里有共同的逻辑而且代码有几百行,但是eat方法里又调用了不同的狗的实现的sleep方法,最终抽象出了共同的部分,又派生了不同的实现,模仿了Java的抽象类