Golang中如何实现子类重写父类方法并被父类调用?

1,012 阅读3分钟

假设这样一种情景: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彻底放弃了继承,推荐使用组合。