关于 go 接口和 go 面向对象问题的一点遐(扯)想(蛋) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
gramyang

关于 go 接口和 go 面向对象问题的一点遐(扯)想(蛋)

  •  
  •   gramyang Jul 23, 2019 4147 views
    This topic created in 2470 days ago, the information mentioned may be changed or developed.

    问题的起因是看到一种很奇怪的写法: 结构体 A 实现了接口 B,其中一个接口 B 嵌套了接口 C、D,另外有一个方法 Fun(),B 的引用是 b。 b.(interface{ Fun() }).Fun() 这里调用的是结构体 A 的方法 Fun()。

    这里的问题就来了,这种写法比较奇怪,但是好歹算是正确的。如何保证它的正确性呢? 放在 Java 里肯定不行,因为 Java 是有类继承的,类的类型可以在子类父类间转换。这种写法只能在 Fun()只有一个实现的情况下才能保证正确性,然而 golang 其实也是有重写这个概念的。

    查了一下发现,类型断言 v := varI.(T),其中 varI 只能是接口。或许是因为这个机制从而保证了上述写法的正确性。

    请指正!

    Supplement 1    Jul 23, 2019
    后来想了想,其实 go 接口的这个特性和 go 的重写没关系。。。。
    Supplement 2    Jul 23, 2019
    最新发现,b.(interface{ Fun() }).Fun()的应用:

    有结构体 A,嵌套结构体 B、C。结构体 A 可以直接调用结构体 B 和结构体 C 的方法。但是结构体 A 实现的接口的引用是不能调用结构体 B 和结构体 C 的方法的。

    b.(interface{ Fun() }).Fun()可以解决这个问题。
    20 replies    2019-07-23 13:56:35 +08:00
    lhx2008
        1
    lhx2008  
       Jul 23, 2019 via Android
    和 java 的没啥关系,只要是名字参数都符合就可以转过去了,也没有啥基类派生类。。
    wweir
        2
    wweir  
       Jul 23, 2019
    这种写法只能人为保证正确性,机制上只提供了一个 ok 返回值供判断
    shingle
        3
    shingle  
       Jul 23, 2019 via Android
    可以编译期判断 var _ A = new(B)
    Mohanson
        4
    Mohanson  
       Jul 23, 2019 via Android
    不知道为什么上来就又要面向对象…何必呢
    mcfog
        5
    mcfog  
       Jul 23, 2019 via Android
    其实就是懒得写一个 Fun 的接口了而已,为此丢了编译期检查,又不愿意判 ok 引入 panic 的风险 :doge:
    gramyang
        6
    gramyang  
    OP
       Jul 23, 2019
    @mcfog 不是,你把接口改成 B 也行。
    我觉得这么写可能是因为阅读方便,原来的 B 接口有 N 多个方法,而你只用 B 接口中的几个方法,把他们组成一个接口,这样阅读性更好些。
    不过我还是觉得这种写法不太自然
    janxin
        7
    janxin  
       Jul 23, 2019
    我理解能力差,没太看懂...能具体解释一下吗
    gramyang
        8
    gramyang  
    OP
       Jul 23, 2019
    @janxin go 的隐式实现接口的特性可以让它凭空实现一个含结构体方法的接口(所谓无中生妈),这种写法其实没卵用,或者说我现在还没有发现它有什么卵用。
    go 用组合代替继承,可以实现重写。
    后来想了想,其实重写和接口没关系。。。
    Hyvi
        9
    Hyvi  
       Jul 23, 2019 via Android
    什么叫接口嵌套接口
    rrfeng
        10
    rrfeng  
       Jul 23, 2019
    A 实现了接口 B,A 有一个实例叫 b
    b.(B).Func() 么这不就是???

    没看懂楼主想说什么……
    本来 b 就可以直接 b.Func() 啊???
    gramyang
        11
    gramyang  
    OP
       Jul 23, 2019
    @rrfeng 关键是这个:
    b.(interface{ Fun() }).Fun()
    gamexg
        12
    gamexg  
       Jul 23, 2019
    go 里面也不行,
    编译时无法保证 b 实现了 Fun() ,运行时如果 b 未实现 Fun() 会 panic。

    最好这样处理下:

    ```
    _fun,ok:=b.(interface{ Fun() })
    if !ok{
    return fmt.ErrorF("")
    }
    _fun.Fun()
    ```
    mcfog
        13
    mcfog  
       Jul 23, 2019 via Android
    @rrfeng Fun 是 A 结构体的,类型为 B 的变量 b 即使实体是 A 也没法直接调到,所以才有那个匿名接口的类型断言
    gramyang
        14
    gramyang  
    OP
       Jul 23, 2019
    @gamexg emmm,一般用 goland 写,goland 会自动检测这个方法有没有被实现。。。
    你要是用 vscode 什么的确实会有这种问题。
    rrfeng
        15
    rrfeng  
       Jul 23, 2019
    @mcfog
    但是 B 没实现 Func 的话,断言会失败啊。
    所以 B 实现了 Func,那么断言之后调用 Func 还是 B 的 Func 吧?
    tairan2006
        16
    tairan2006  
       Jul 23, 2019
    没法保证,你要人肉保证

    void*在 c 里面可以随便转成函数指针
    rrfeng
        17
    rrfeng  
       Jul 23, 2019   1
    看了最新的补充才看懂是在说什么……你们怎么就一下子明白了楼主的意思的???
    reus
        18
    reus  
       Jul 23, 2019
    语言表达能力有待提高……

    “结构体 A 实现了接口 B ”,这句 ok
    “其中一个接口 B 嵌套了接口 C、D ”,接口 B 就只有一个,“其中一个”似乎多余
    “另外有一个方法 Fun()”,指代不明,究竟是 A 类型有 Fun 方法,还是 B 接口有 Fun 方法?
    “ B 的引用是 b ”,意义不明,B 是一个接口类型,接口类型的引用是啥?是指“有一个变量叫 b,类型是 B ”?

    第一段就不知所云,后面两段也不知道在说什么。

    后面那个“最新发现”,怎么忽然就变成结构体的嵌套了。后面这不就是最基本的类型断言么,感觉就是学得太少想得太多而已。
    GeruzoniAnsasu
        19
    GeruzoniAnsasu  
       Jul 23, 2019
    感觉就是某种 down cast
    那么为什么不 b.(A)呢?
    zzlettle
        20
    zzlettle  
       Jul 23, 2019
    b.(interface{ Fun() }).Fun()

    本人学习 GOLANG 不久,这个用法不太明白
    这行代码想要解决什么问题了?

    上面有人写的这段代码,我到能看懂
    ```
    _fun,ok:=b.(interface{ Fun() })
    if !ok{
    return fmt.ErrorF("")
    }
    _fun.Fun()
    ```
    这个是在判断,b 是否实现了含有 fun()的一个接口
    About     Help     Advertise     Blog     API     FAQ     Solana     4712 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 53ms UTC 00:13 PVG 08:13 LAX 17:13 JFK 20:13
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86