假设这样一种情景:A是父类,B是继承了A的子类。在A中,DoMoves是一个public的函数,它会调用getEats()函数。B重写了这个getEats()函数,从而可以实现new B().DoMoves()可以正常调用到B中的getEats()函数。
在Java中,B可以重写A的getEats()函数,B依旧可以沿用A的DoMoves()行为。
B的行为大部分与A一致,只有个别函数需要修改。在Java中非常容易实现这一点。
class A {
String DoMoves() {
return getEats();
}
String getEats() {
return "A";
}
}
class B extends A {
@Override
String getEats() {
return "B";
}
}
class Solution {
public static void main(String[] args) {
A a = new B();
System.out.println(a.DoMoves());// 输出为B
}
}
在Golang中,要想实现这一点非常困难。
如下代码,输出为A。这说明golang里面调用GetEats()的时候依旧是调用父类的getEats,B中的函数重写并没有影响A。
package main
import "fmt"
type A struct {
}
func (a *A) DoMoves() string {
ans := a.GetEats()
return ans
}
func (a *A) GetEats() string {
return "A"
}
type B struct {
*A
}
func (b *B) GetEats() string {
return "B"
}
func main() {
b := &B{}
fmt.Println(b.DoMoves())//输出为A
}
那么在golang中如何实现B重写A的GetEats呢?我们需要回到最初的需求上来看。B的功能大部分与A都是一致的,只有一个函数GetEats需要做一些修饰。那么为什么不让A持有一个GetEatsFunc呢?A直接调用GetEatsFunc就完事了。
package main
import "fmt"
type A struct {
getEats func() string
}
func NewA(getEats func() string) *A {
return &A{
getEats: func() string {
return "A"
},
}
}
func (a *A) DoMoves() string {
ans := a.getEats()
return ans
}
type B struct {
A
}
func newB() *B {
return &B{A: A{getEats: func() string {
return "B"
}}}
}
func main() {
b := newB()
fmt.Println(b.DoMoves()) //输出为B
}
如果B持有一些数据,单单使用一个GetEats不够用怎么办?把getEatsFunc改写成interface,A持有一个这样的interface即可。
回到题目中的问题:golang中如何实现子类重写父类的个别函数?
答案是:你不需要这样做,不需要让子类重写父类的函数。**
**
Golang的思想就是:组合大于继承,组合大于继承。Golang中没有继承,只有组合。
通过组合我们能够实现同样的效果,那么我们为什么还需要继承呢?这就是golang的设计理念。
当我看到golang子类无法重写父类的方法的时候,我感觉golang太垃圾了。实际上是我没有理解goalng的设计理念。大多数面向对象功能都能够使用组合来实现。
学习golang,我们需要对自己已有的面向对象思想做一些改进。面向对象不一定通过继承来实现,继承会导致代码复杂度上升。
看看其它语言是怎么做的吧。
C++支持多重继承,需要用很复杂的方式去解决菱形继承的表达问题。
Java支持实现多个接口,但是只支持继承一个类。使用单一继承降低了继承的复杂度。
Python支持多重继承,按照继承顺序决定调用哪个函数。
Golang彻底放弃了继承,推荐使用组合。