jeudi 19 avril 2018

Reflect Type of embedding struct

I'm currently trying myself on some OOP-esque Go, following a tutorial I found online.

So far, it's quite fascinating (reminds me of trying to force OOP into ANSI-C).

However, there's just one thing bothering me that I can't seem to solve.

How would I be able to reflect the Type name of the embedding struct?

All info I found online says one can't reflect over the embedding struct, as the embedded struct has no direct access to it.

Is this entirely accurate? If so, what would be the correct way to solve the following problem (code below)?

Basically, the program prints out the name of three individual animals, followed by the Type name of the embedded struct in parentheses, followed by the respective animal's "sound".

i e for the dog named "Rover", it will print "Rover (Animal): BARK BARK".

Now, obviously, "Rover (Animal)" isn't particularly informative. Ideally, this should be "Rover (Dog)" (the Type name of the embedding struct, rather than the embedded struct).

Therein lies my problem. How may I be able to reflect the Type of the embedding struct, so "Rover (Animal)" becomes "Rover ("Dog"), "Julius (Animal)" becomes "Julius (Cat)", etc?

package main

import (
    "fmt"
    "reflect"
)

type Animal struct {
    Name string
    mean bool
}

type AnimalSounder interface {
    MakeNoise()
}

type Dog struct {
    Animal
    BarkStrength int
}

type Cat struct {
    Basics       Animal
    MeowStrength int
}

type Lion struct {
    Basics       Animal
    RoarStrength int
}

func (dog *Dog) MakeNoise() {
    dog.PerformNoise(dog.BarkStrength, "BARK")
}

func (cat *Cat) MakeNoise() {
    cat.Basics.PerformNoise(cat.MeowStrength, "MEOW")
}

func (lion *Lion) MakeNoise() {
    lion.Basics.PerformNoise(lion.RoarStrength, "ROAR!!  ")
}

func MakeSomeNoise(animalSounder AnimalSounder) {
    animalSounder.MakeNoise()
}

func main() {
    myDog := &Dog{
        Animal{
            Name: "Rover", // Name
            mean: false,   // mean
        },
        2, // BarkStrength
    }

    myCat := &Cat{
        Basics: Animal{
            Name: "Julius",
            mean: true,
        },
        MeowStrength: 3,
    }

    wildLion := &Lion{
        Basics: Animal{
            Name: "Aslan",
            mean: true,
        },
        RoarStrength: 5,
    }

    MakeSomeNoise(myDog)
    MakeSomeNoise(myCat)
    MakeSomeNoise(wildLion)
}

func (animal *Animal) PerformNoise(strength int, sound string) {
    if animal.mean == true {
        strength = strength * 5
    }

    fmt.Printf("%s (%s): \n", animal.Name, reflect.ValueOf(animal).Type().Elem().Name())

    for voice := 0; voice < strength; voice++ {
        fmt.Printf("%s ", sound)
    }

    fmt.Println("\n")
}





Aucun commentaire:

Enregistrer un commentaire