今天写代码遇到了一个坑:
package main
import "fmt"
type Person interface {
Say()
Name()
}
type Parent struct {
}
func (s *Parent) Say() {
fmt.Println("i am " + s.Name())
}
func (s *Parent) Name() string {
return "parent"
}
type Child struct {
Parent
}
func (s *Child) Name() string {
return "child"
}
func main() {
var c Child
// i am parent
c.Say()
c1 := &Child{}
// i am parent
c1.Say()
}
这个输出 // i am parent
, 感觉 go 的组合真的和继承没有任何关系.
1
yokyj 2021-03-29 17:56:27 +08:00
golang 确实是没有真正的继承,但是你这里的问题是在于 Child 没有实现 Say 函数,也就是没有实现 person 接口
|
2
anonydmer 2021-03-29 18:10:43 +08:00
接口根本没用上,而且 Name() 函数接口和实现中签名也不一致
|
4
jasonkayzk 2021-03-29 20:01:54 +08:00
首先,你的 interface 写的有问题,Name() 函数应该是有返回值的,否则下面的 struct 是没有实现这个接口的:
```go type Person interface { Say() Name() string } ``` 其次,要注意 Go 里面只有 “组合”(类似于 Spring 框架里面通过组合进行依赖注入?),没有继承; 在组合的时候,子 struct 会保留原来父 struct 中的方法(除非子类重写这个方法);并且 Go 中的方法(或者说函数)只有 Receiver 的说法,而不是属于某个类或者子类! 所以,当子类 Child 调用 Say 方法的时候,由于 Child 本身没有实现 Child 方法,所以会调用到 Child 组合而来的 Parent ; 如果你给 Parent 成员变量取个名字,例如: ```go type Child struct { p Parent } ``` 其实他调用的是 c.p.Name(); 大概这样。 |
5
cmdOptionKana 2021-03-29 20:15:34 +08:00 via Android
真正的继承有很多问题,因此比较新的语言都看轻了继承,一些老语言也增加非继承的组合的支持。
|
6
tabris17 2021-03-29 20:45:40 +08:00 via iPhone
是你的代码有问题,s.Name()调用是静态绑定的,如果此处要实现动态分发,那就要先实现一个包含 Name()方法的 named 接口,然后把 s 转换成接口再调用
|
7
rrfeng 2021-03-29 21:15:13 +08:00 1
你这个 Person 没有任何卵用(逃
|
8
seth19960929 OP |
9
seth19960929 OP @rrfeng 因为我在别的方法需要使用 Person 接口, 只是实例代码没用
|
10
seth19960929 OP @tabris17 我要表达的是组合的方式, 和接口无关. 我的其他代码没给. 一样是用 Person 接口去调用.
|
11
tabris17 2021-03-31 09:37:03 +08:00
@seth19960929 组合就用显式调用,4 楼已经说了。如果要实现动态分发(多态)就得用接口
|