In Go, how can I get the TypeOf a type using an anonymous field method?

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

Upvotes: 5

Views: 227

Answers (2)

Intermernet
Intermernet

Reputation: 19388

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

Upvotes: 2

zzzz
zzzz

Reputation: 91253

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())
}

Playground


Output:

I am a *main.Cod

Upvotes: 9

Related Questions