dtpt75860 2019-06-21 00:32
浏览 93
已采纳

如何使用子方法强制多态?

I'm coming from a language like C++ where OOP is well defined and polymorphism is commonly used. I'm new using Go and I'm trying to call child method from a polymorphism and I have no idea what's is the right pattern.

I created two structs as u'll see, and I defined 2 methods fun1 and fun2 where in the base struct i override only one of them, and in the parent i'm calling it. If the polymorphism is correct, this child method should be called and at least in my example, this is not happenning

Here is the code:

package main

import (
    "fmt"
)

type A struct {

}

type B struct {
    A
}

func (a* A) fun1() {
    fmt.Println("I'm in A.fun1()")
    a.fun2()
}

func (a* A) fun2() {
    fmt.Println("I'm in A.fun2()")
}


func (b* B) fun2() {
    fmt.Println("I'm in B.fun2()")
}

func main() {
    b := B{}
    b.fun1()    
}

You can try it here: https://play.golang.org/p/s7xZun-6Otx

The output was

I'm in A.fun1()
I'm in A.fun2()

and I wasexpected

I'm in A.fun1()
I'm in B.fun2()

How can I do that? what's the right way for having a good design in Go for this?

Regards

  • 写回答

1条回答 默认 最新

  • dongshan4518 2019-06-21 01:15
    关注

    Go objects are generally built around composition as opposed to inheritance, as the pattern you are using would make it very difficult for the A structure to make any assumptions about what fun2 is doing. The polymorphism in go is done at the interface level. The preferred method is to pull the "overridable" fun2 functionality into a separate interface type, which is passed in to the fun1 function or stored in the object containing fun1. Without the specifics of how you would be doing this, it's difficult to make a reasonable example but this is the pattern:

    package main
    
    import (
        "fmt"
    )
    
    type fun2er interface {
        fun2()
    }
    
    type A struct {
        B fun2er
    }
    
    func (a* A) fun1() {
        fmt.Println("I'm in A.fun1()")
        a.B.fun2()
    }
    
    type B1 struct {}
    
    func (b B1) fun2() {
        fmt.Println("I'm in B1.fun2()")
    }
    
    type B2 struct {}
    
    func (b B2) fun2() {
        fmt.Println("I'm in B2.fun2()")
    }
    
    func main() {
        a1 := A{B: B1{}}
        a2 := A{B: B2{}}
    
        a1.fun1()
        a2.fun1()
    }
    

    This will print:

    I'm in A.fun1()
    I'm in B1.fun2()
    I'm in A.fun1()
    I'm in B2.fun2()
    

    Edit:

    I wanted to add a little more color on how this works under the hood. The way you are "extending" your A type with B is called struct embedding, and is mostly syntactic sugar for adding a field to B of type A named the same as its type:

    type A struct {}
    
    type B struct {
        A A
    }
    

    The key difference being that when using struct embedding you can call A methods directly on a B object b.fun1(). When this is called, the this-like a parameter that gets passed to fun1 is not the entire B object, but just the A field inside of it (as though you called b.A.fun1()) which is why when fun1 calls fun2, it is calling the A implementation, as it has no access to the B object it is stored inside.

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

报告相同问题?

悬赏问题

  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大
  • ¥15 Oracle中如何从clob类型截取特定字符串后面的字符
  • ¥15 想通过pywinauto自动电机应用程序按钮,但是找不到应用程序按钮信息
  • ¥15 如何在炒股软件中,爬到我想看的日k线
  • ¥15 seatunnel 怎么配置Elasticsearch
  • ¥15 PSCAD安装问题 ERROR: Visual Studio 2013, 2015, 2017 or 2019 is not found in the system.
  • ¥15 (标签-MATLAB|关键词-多址)
  • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
  • ¥500 52810做蓝牙接受端