英文:
In Go, how can I get the TypeOf a type using an anonymous field method?
问题
如何使用匿名字段(或超类)获取结构体的正确类型?
我试图让这个鱼描述自己为鳕鱼:
package main
import (
"fmt"
"reflect"
)
type Fish struct {
}
func (self *Fish) WhatAmI() string {
return reflect.TypeOf(self).String()
}
type Cod struct {
Fish
}
func main() {
c := new(Cod)
fmt.Println("我是一个", c.WhatAmI())
}
我得到的输出是:
我是一个 *main.Fish
我想要的是:
我是一个 *main.Cod
英文:
How do I get the correct Type of the struct using the anonymous field (or superclass)?
I am trying to make this fish describe itself as a cod:
package main
import (
"fmt"
"reflect"
)
type Fish struct {
}
func (self *Fish) WhatAmI() string {
return reflect.TypeOf(self).String()
}
type Cod struct {
Fish
}
func main() {
c := new(Cod)
fmt.Println("I am a", c.WhatAmI())
}
The output I get is:
I am a *main.Fish
What I want is:
I am a *main.Cod
答案1
得分: 9
你得到了正确的答案。你想要得到的答案是错误的。
在
func (f *Fish) WhatAmI() string {
return reflect.TypeOf(f).String()
}
f
是类型为 *main.Fish
的,甚至在声明时就指定了它的类型为 f *Fish
。因此它永远不可能是类型为 *main.Cod
的。
混淆的可能来源是:Cod
的方法集继承了它的匿名嵌入字段 Fish
的方法集,并且没有覆盖它。因此,在 Cod
的实例上调用 WhatAmI
方法会将调用委托给 Fish.WhatAmI
,但是接收者现在是类型为 *main.Fish
的嵌入字段。
覆盖继承方法的示例:
package main
import (
"fmt"
)
type Fish struct {
}
func (f *Fish) WhatAmI() string {
return fmt.Sprintf("%T", f)
}
type Cod struct {
Fish
}
func (c *Cod) WhatAmI() string {
return fmt.Sprintf("%T", c)
}
func main() {
c := new(Cod)
fmt.Println("I am a", c.WhatAmI())
}
输出:
I am a *main.Cod
英文:
You are getting the correct answer. The answer you want to get is wrong.
In
func (f *Fish) WhatAmI() string {
return reflect.TypeOf(f).String()
}
f
is of type *main.Fish
, it's even declared to be of that type (f *Fish
). Thus it cannot ever be of type *main.Cod
.
The probable source of confusion: The method set of Cod
inherites the method set of its embedded, anonymous field Fish
and doesn't override it. Thus invoking WhatAmI
on an instance of Cod
"delegates" the call to Fish.WhatAmI
, but the receiver is now the embedded field of type *main.Fish
.
Example with overriding the inherited method:
package main
import (
"fmt"
)
type Fish struct {
}
func (f *Fish) WhatAmI() string {
return fmt.Sprintf("%T", f)
}
type Cod struct {
Fish
}
func (c *Cod) WhatAmI() string {
return fmt.Sprintf("%T", c)
}
func main() {
c := new(Cod)
fmt.Println("I am a", c.WhatAmI())
}
Output:
I am a *main.Cod
答案2
得分: 2
对于一个相当通用的解决方案,你可以将WhatAmI
函数从Fish
类型中分离出来,并使用一个空接口(参见Andrew Gerrand的《反射法则》),然后在该接口上检查类型:
package main
import (
"fmt"
"reflect"
)
type Fish struct {
}
type Cod struct {
Fish
}
func WhatAmI (self interface{}) string {
return reflect.TypeOf(self).String()
}
func main() {
c := new(Cod)
fmt.Println("I am a", WhatAmI(c))
}
输出:
I am a *main.Cod
英文:
For a fairly generic solution, you could separate the WhatAmI
function from the Fish
type and use an empty interface (see Andrew Gerrand's "The Laws of Reflection"), and just check the type on that:
package main
import (
"fmt"
"reflect"
)
type Fish struct {
}
type Cod struct {
Fish
}
func WhatAmI (self interface{}) string {
return reflect.TypeOf(self).String()
}
func main() {
c := new(Cod)
fmt.Println("I am a", WhatAmI(c))
}
Gives:
I am a *main.Cod
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论