dongshilve4392 2018-08-30 22:37
浏览 302
已采纳

Golang继承和方法重写

Clarification: I'm just learning GO, and came across this problem.

I'm trying to implement a "class" that inherit a method that invokes a "virtual" method that should be implemented by the child class. Here's my code:

https://play.golang.org/p/ysiaPwARkvl

package main

import (
    "fmt"
    "sync"
)

type Parent struct {
  sync.Mutex
  MyInterface
}

func (p *Parent) Foo() {
  p.Lock()
  defer p.Unlock()
  p.Bar()
}

func (p *Parent) B(){
  panic("NOT IMPLEMENTED")
}

func (p *Parent) A() {
  p.Lock()
  defer p.Unlock()
  p.B()
}

type MyInterface interface {
  Foo()
  Bar()
}

type Child struct {
  Parent
  Name string
}

func (c *Child) Bar(){
  fmt.Println(c.Name)
}

func (c *Child) B(){
  fmt.Println(c.Name)
}

func main() {
  c := new(Child)
  c.Name = "Child"
  // c.A() panic
  c.Foo() // pointer error
}

I left out some code regarding the sync.Mutex that does some async update to the values of Child.

So apparently in A() or Foo() the pointer p have type Parent. How should I change my code so that A/Foo refer to B/Bar defined in the Child class?

  • 写回答

1条回答 默认 最新

  • doutou19761022 2018-08-31 04:56
    关注

    You're wanting an is-a relationship (inheritance) when Go only provides has-a relationships (composition):

    • Go has no inheritance, thus there is no is-a relationship between two types. Child is not a kind of Parent, so a pointer to a Parent cannot retain a pointer to a Child; Child has-a Parent contained within it instead.

    Because there is no is-a relationship between Parent and Child, Parent.Foo cannot receive an object of type Child, nor can it use any of the methods that Child implements. Also, this means that no Parent can access any method defined on a Child such as Bar() or B() directly.

    Typically, Parent will not need to call some method in Child. If it does, you'd pass the Parent method an argument, such as an interface that Child satisfies for you to call the method through the interface or a closure that calls the Child method:

    // Use of an interface that Child satisfies.
    type Beta interface {
        B()
    }
    func (p *Parent) A(b Beta) {
        p.Lock()
        defer p.Unlock()
        b.B()
    }
    
    // Use of a closure.
    func (p *Parent) Foo(bar func()) {
        p.Lock()
        defer p.Unlock()
        bar()
    }
    func callFoo(p *Parent, c *Child) {
        callBar := func() {
            c.Bar()
        }
        p.Foo(callBar)
    }
    
    func (c *Child) Bar() {
        // stub
    }
    
    func (c *Child) B() {
        // stub
    }
    

    You get the Child can call Parent method behavior for free, but it only appears similar to inheritance. child.Foo() actually performs child.Parent.Foo(), which means Parent.Foo still receives a Parent instance (hence the name), not a Child instance.

    However, Parent cannot access any information about Child that Child does not explicitly share. Interfaces and closures can act as mechanisms between two classes analogous to the friend keyword in C++, except they're more restrictive than the friend keyword. After all, Child doesn't need to share everything with Parent, just the bits that it wants to share, somewhat similar to this pattern in C++. Personally I would prefer interfaces for this as it allows your Parent "class" to work with multiple types that all satisfy a common interface, making it pretty much the same as calling the method from a normal function or an entirely unrelated type's method.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 如何使用canvas在图片上进行如下的标注,以下代码不起作用,如何修改
  • ¥15 Windows 系统cmd后提示“加载用户设置时遇到错误”
  • ¥50 vue router 动态路由问题
  • ¥15 关于#.net#的问题:End Function
  • ¥15 无法import pycausal
  • ¥15 VS2022创建MVC framework提示:预安装的程序包具有对缺少的注册表值的引用
  • ¥15 weditor无法连接模拟器Local server not started, start with?
  • ¥20 6-3 String类定义
  • ¥15 嵌入式--定时器使用
  • ¥30 Windows Server 2016利用兩張網卡處理兩個不同網絡