Golang中如何在子类重写父类方法并调用

Golang中如何在子类重写父类方法并调用

type A struct {
}

func NewA() *A {
	return &A{}
}

func (a *A) Foo() {
	fmt.Println("Foo of A")
}

func (a *A) Bar() {
	//More codes...
	a.Foo()
	//More codes...
}

type B struct {
	*A
}

func NewB() *B {
	return &B{
		A: NewA(),
	}
}

func (b *B) Foo() {
	fmt.Println("Foo of B")
}

func main() {
	b := NewB()
	b.Bar()
}

我想在 B 中重写 Foo() 方法,并让 B 继承 A 的所有内容。 当调用 b.Bar() 时,我认为它应该打印:

Foo of B

但实际并没有。

在 Java 中,它是这样工作的:

public class Main {

    class A {
        public void foo() {
            System.out.println("Foo of A");
        }

        public void bar() {
            foo();
        }

    }

    class B extends A {
        public void foo() {
            System.out.println("Foo of B");
        }
    }

    public void Test01() {
        B b = new B();
        b.bar();
    }

    public static void main(String[] args) {
        Main m = new Main();
        m.Test01();
    }
}

更多关于Golang中如何在子类重写父类方法并调用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

Go 的工作方式并非如此。它没有像 Java 那种面向对象编程意义上的继承。如果你有那样的背景,这个演讲可能有助于你更好地理解 Go 如何处理这个主题:GopherCon Europe 2022: Yarden Laifenfeld - From OOP to Go - YouTube

更多关于Golang中如何在子类重写父类方法并调用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,通过嵌入实现的"继承"不会像Java那样支持多态方法调用。当ABar()方法调用a.Foo()时,它调用的是AFoo()方法,而不是B的重写版本。

要实现类似Java的多态行为,你需要使用接口。以下是修改后的代码:

package main

import "fmt"

// 定义接口
type Fooer interface {
    Foo()
}

type A struct {
    // 保存对实际实例的引用
    self Fooer
}

func NewA() *A {
    a := &A{}
    a.self = a
    return a
}

func (a *A) Foo() {
    fmt.Println("Foo of A")
}

func (a *A) Bar() {
    // 通过接口调用Foo方法
    a.self.Foo()
}

type B struct {
    *A
}

func NewB() *B {
    b := &B{
        A: NewA(),
    }
    // 将self指向B实例
    b.A.self = b
    return b
}

func (b *B) Foo() {
    fmt.Println("Foo of B")
}

func main() {
    b := NewB()
    b.Bar()  // 输出: Foo of B
}

或者,更简洁的方式是使用接口组合:

package main

import "fmt"

type Fooer interface {
    Foo()
}

type Barer interface {
    Fooer
    Bar()
}

type A struct{}

func (a *A) Foo() {
    fmt.Println("Foo of A")
}

func (a *A) Bar() {
    a.Foo()
}

type B struct {
    *A
}

// 重写Foo方法
func (b *B) Foo() {
    fmt.Println("Foo of B")
}

// 重写Bar方法以调用正确的Foo
func (b *B) Bar() {
    b.Foo()
}

func main() {
    var barer Barer = &B{A: &A{}}
    barer.Bar()  // 输出: Foo of B
}

如果你需要保持Bar()方法在父类中定义,但调用子类的方法,第一种方案更合适。第二种方案需要你在每个子类中都重写Bar()方法。

回到顶部