
问题的起因是看到一种很奇怪的写法: 结构体 A 实现了接口 B,其中一个接口 B 嵌套了接口 C、D,另外有一个方法 Fun(),B 的引用是 b。 b.(interface{ Fun() }).Fun() 这里调用的是结构体 A 的方法 Fun()。
这里的问题就来了,这种写法比较奇怪,但是好歹算是正确的。如何保证它的正确性呢? 放在 Java 里肯定不行,因为 Java 是有类继承的,类的类型可以在子类父类间转换。这种写法只能在 Fun()只有一个实现的情况下才能保证正确性,然而 golang 其实也是有重写这个概念的。
查了一下发现,类型断言 v := varI.(T),其中 varI 只能是接口。或许是因为这个机制从而保证了上述写法的正确性。
请指正!
1 lhx2008 Jul 23, 2019 via Android 和 java 的没啥关系,只要是名字参数都符合就可以转过去了,也没有啥基类派生类。。 |
2 wweir Jul 23, 2019 这种写法只能人为保证正确性,机制上只提供了一个 ok 返回值供判断 |
3 shingle Jul 23, 2019 via Android 可以编译期判断 var _ A = new(B) |
4 Mohanson Jul 23, 2019 via Android 不知道为什么上来就又要面向对象…何必呢 |
5 mcfog Jul 23, 2019 via Android 其实就是懒得写一个 Fun 的接口了而已,为此丢了编译期检查,又不愿意判 ok 引入 panic 的风险 :doge: |
6 gramyang OP @mcfog 不是,你把接口改成 B 也行。 我觉得这么写可能是因为阅读方便,原来的 B 接口有 N 多个方法,而你只用 B 接口中的几个方法,把他们组成一个接口,这样阅读性更好些。 不过我还是觉得这种写法不太自然 |
7 janxin Jul 23, 2019 我理解能力差,没太看懂...能具体解释一下吗 |
8 gramyang OP @janxin go 的隐式实现接口的特性可以让它凭空实现一个含结构体方法的接口(所谓无中生妈),这种写法其实没卵用,或者说我现在还没有发现它有什么卵用。 go 用组合代替继承,可以实现重写。 后来想了想,其实重写和接口没关系。。。 |
9 Hyvi Jul 23, 2019 via Android 什么叫接口嵌套接口 |
10 rrfeng Jul 23, 2019 A 实现了接口 B,A 有一个实例叫 b b.(B).Func() 么这不就是??? 没看懂楼主想说什么…… 本来 b 就可以直接 b.Func() 啊??? |
12 gamexg Jul 23, 2019 go 里面也不行, 编译时无法保证 b 实现了 Fun() ,运行时如果 b 未实现 Fun() 会 panic。 最好这样处理下: ``` _fun,ok:=b.(interface{ Fun() }) if !ok{ return fmt.ErrorF("") } _fun.Fun() ``` |
14 gramyang OP @gamexg emmm,一般用 goland 写,goland 会自动检测这个方法有没有被实现。。。 你要是用 vscode 什么的确实会有这种问题。 |
16 tairan2006 Jul 23, 2019 没法保证,你要人肉保证 void*在 c 里面可以随便转成函数指针 |
17 rrfeng Jul 23, 2019 看了最新的补充才看懂是在说什么……你们怎么就一下子明白了楼主的意思的??? |
18 reus Jul 23, 2019 语言表达能力有待提高…… “结构体 A 实现了接口 B ”,这句 ok “其中一个接口 B 嵌套了接口 C、D ”,接口 B 就只有一个,“其中一个”似乎多余 “另外有一个方法 Fun()”,指代不明,究竟是 A 类型有 Fun 方法,还是 B 接口有 Fun 方法? “ B 的引用是 b ”,意义不明,B 是一个接口类型,接口类型的引用是啥?是指“有一个变量叫 b,类型是 B ”? 第一段就不知所云,后面两段也不知道在说什么。 后面那个“最新发现”,怎么忽然就变成结构体的嵌套了。后面这不就是最基本的类型断言么,感觉就是学得太少想得太多而已。 |
19 GeruzoniAnsasu Jul 23, 2019 感觉就是某种 down cast 那么为什么不 b.(A)呢? |