V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
honmaple
V2EX  ›  问与答

golang 类似 Python 的实例方法?

  •  
  •   honmaple · 2018-02-01 16:24:31 +08:00 · 1817 次点击
    这是一个创建于 2487 天前的主题,其中的信息可能已经有所发展或是发生改变。
    package main
    
    type Parent struct {
    }
    
    func (self *Parent) Run() {
        self.Test()
    }
    func (self *Parent) Test() {
        println("parent")
    }
    
    type Child struct {
        Parent
    }
    
    func (self *Child) Test() {
        println("child")
    }
    
    func main() {
        parent := Parent{}
        parent.Run()
    
        child := Child{}
        child.Run()
    }
    

    请教一下有什么好的方法可以child调用自己的Test呢?

    Run是一个公共函数,不想写多次

    8 条回复    2018-02-01 22:14:53 +08:00
    popbones
        1
    popbones  
       2018-02-01 17:54:30 +08:00
    我印象里不行。

    最简单的方法是:

    func (self *Child) Run() {
    self.Parent.Run()
    }

    因为 Golang 的理念,我理解接口设计是这样的

    type Testable interface{
    Test();
    }

    type Runable interface{
    popbones
        2
    popbones  
       2018-02-01 17:55:26 +08:00
    Testable
    Run()
    }


    电脑一卡就变两条了。。。
    l1093178
        3
    l1093178  
       2018-02-01 18:27:12 +08:00
    Struct embedding 不是继承
    https://golang.org/ref/spec#Struct_types
    https://golang.org/ref/spec#Method_values
    这个地方 child.Run 会被 Resolve 到 Parent.Run ,所以说 receiver 的 type 也是 Parent,然后调用 test 的时候自然也是 Parent.Test
    mengzhuo
        4
    mengzhuo  
       2018-02-01 19:00:33 +08:00 via iPhone
    大哥…… Test 模块直接命名好,丢在_test.go 结尾的文件就能跑了
    rrfeng
        5
    rrfeng  
       2018-02-01 19:08:15 +08:00 via Android
    用 interface !
    honmaple
        6
    honmaple  
    OP
       2018-02-01 19:19:29 +08:00
    @popbones @l1093178 child.Run() 会调用 self.Parent.Run() 这个我是知道的,现在我想让 child 调用自身的 Test,这有什么好的办法吗?

    @mengzhuo 可能没理解我的意思

    @rrfeng 可以具体一些吗?

    我目前想到的方法是把 child 作为参数传入 Run 里,再在 Run 里调用 child.Test()
    popbones
        7
    popbones  
       2018-02-01 19:34:07 +08:00 via iPhone
    我说的印象里不行是指我印象里 golang 不支持这个,如果非要一能调用子类方法的基类方法实现的话 golang 基本上这种情况就建议放弃面向对象把基类方法改写成包全局函数

    func Run(t Testable) {
    t.Test()
    }

    否则的话如果你非要面向对象的这个功能,你可以用反射,不过这就跟语言的设计初衷背道而驰了

    总而言之,不要用 golang 实现 python 或 java 的设计,会很痛苦的
    rrfeng
        8
    rrfeng  
       2018-02-01 22:14:53 +08:00
    其实没想象出来什么样的场景会嵌套 struct 并且还要有同名的方法……

    如果需要的是同名方法,那么用 type Runable interface{ func Run() } 来存储实例,各自调用各自的 run 方法。

    如果需要的是字段嵌套,那么换个方法名不行吗? parent.run() child.run2() 像这样
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1895 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 16:20 · PVG 00:20 · LAX 08:20 · JFK 11:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.