5

匿名フィールド (またはスーパークラス) を使用して構造体の正しいタイプを取得するにはどうすればよいですか?

私はこの魚が自分自身をタラと表現するようにしようとしています:

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

私が得る出力は次のとおりです。

I am a *main.Fish

私が欲しいのは:

I am a *main.Cod
4

2 に答える 2

9

あなた正しい答えを得ています。あなたが得たい答えは間違っています。

func (f *Fish) WhatAmI() string {
        return reflect.TypeOf(f).String()
}

f 型である場合、その型 ( ) であると*main.Fishさえ宣言さf *Fishれています。したがって、タイプになることはありません*main.Cod

考えられる混乱の原因: のメソッドCodセットは、埋め込まれた匿名フィールドのメソッド セットを継承し、Fishそれをオーバーライドしません。したがってWhatAmI、 のインスタンスを呼び出すと、へCodの呼び出しが「デリゲート」されます、レシーバーはタイプ の埋め込みフィールドになります。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
于 2013-06-04T11:26:51.667 に答える
2

かなり一般的な解決策として、WhatAmI関数をFish型から分離し、空のインターフェイスを使用して ( Andrew Gerrand の "The Laws of Reflection"を参照)、その型を確認するだけです。

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
于 2013-06-04T12:19:12.603 に答える