3 回答
TA贡献1798条经验 获得超3个赞
获得这种后期绑定行为的方法是使用接口。IfIntroduce
是接口上的一个sayName
方法,它需要一个方法,那么Human
和Child
都将满足该接口,并且可以Introduce
自己满足,并且sayName
在任何一种情况下都将调用正确的方法,因为它将通过接口类型而不是 via 分派Human
。
TA贡献1785条经验 获得超8个赞
你想做的事情是不可能的。正如你所说,Human
类型永远无法知道它的嵌入Child
型和为此时Introduce
被调用它没有调用方式Child
的类型版本sayName()
。您正在尝试反转关系,让嵌入类型在嵌入器中调用其方法的另一个版本。
嵌入类型的方法被提升到嵌入器的范围,但这是一条单行道,这是明智的。在这种情况下,您只需要以不同的方式构造您的代码。最有可能的是,您正在寻找的任何行为都可以通过使用接口而不是嵌入来实现。我会提供更多示例,但是对于您的代码示例,没什么好说的,显然要解决这里的问题,您只需调用sayName()
并且永远不会Introduce
首先定义,因为它什么都不做。
您可能应该只嵌入相反的方向。Human
不包含对的引用,Child
但Child
确实有对Human
和的引用,在这种情况下,两者都有对 的定义sayName()
,Child
可以Human
通过做来调用's c.Human.sayName()
。所以我的直觉说你嵌入了错误的方向,或者你应该使用接口。这纯粹是一个假设,但我猜你可能有错误的想法,因为你指的Human
是和“成人”(如父母)和Child
作为孩子(就像一个孩子班)。根本不是这种情况。嵌入与组合相同,只是嵌入类型的方法和字段被提升或提升,或者您喜欢说它们被移动到嵌入器范围的任何术语。话虽如此,我在 SO 上看到了很多关于这个的困惑,这几乎总是因为提问者把它看作是继承,而实际上它是组合。
TA贡献1772条经验 获得超8个赞
我想错了。正如 hobbs 和 evanmcdonnal 所说,“正确”的做法是让 Introduce() 函数成为一个带有接口参数的函数,然后创建一个 Child 和 Human 都实现的接口。
以下给出了所需的输出:
package main
import "fmt"
type Talker interface {
sayName() error
}
type Human struct {
age uint
name string
}
func (h Human) sayName() error {
fmt.Println("I am the Adult")
return nil
}
type Child struct {
Human
}
func Introduce(t Talker) error {
t.sayName()
return nil
}
func (c Child) sayName() error {
fmt.Println("I am the Child")
return nil
}
func main() {
h := Human{}
Introduce(h)
c := Child{Human{}}
Introduce(c)
}
- 3 回答
- 0 关注
- 156 浏览
添加回答
举报