Tuesday, 26 April 2016

go - One type is coerced into another, can a method to determine the type of the receiver?



If types T1 and T2 are based on type T, and type T only comes into existence from a NewT1() or NewT2(), is there any way a function func (*T) WhoAmI() can know whether it "really" is a T1 or T2?




package main

import "fmt"
import "reflect"

type T struct { s string }
func (v *T) WhoAmI() string {

// pull type name with reflect
fmt.Println( reflect.TypeOf(v).Elem().Name() ) // always prints "T"!

// todo: if I am actually T1

return "T1"
// todo: else if I am actually T2
return "T2"
}

type T1 T
func NewT1( s string ) T1 { return T1{ s } }

type T2 T
func NewT2( s string ) T2 { return T2{ s } }


func main() {
var t1 = T1{ "xyz" }
var t2 = T2{ "pdq" }
s1 := ((*T)(&t1)).WhoAmI() // would like to return "T1"
s2 := ((*T)(&t2)).WhoAmI() // would like to return "T2"
fmt.Println( s1, s2 )
}



to speak technically:



once t1 type T1 is coerced into type T so func (*T) WhoAmI() can be called, does t1 completely lose the fact that its type is really T1? if not, how do we reclaim the knowledge from the perspective of a method receiving type T?



to speak generally:



in other words, if one type is based on another, if a variable of the derived type is coerced into the base type to run a method, can that method learn the real type of the receiver who called it?


Answer



No, it's not possible. Creating a new type from an old one is not like creating a new class that inherits from a parent class in an class-based language. In your case T knows nothing about either T1 or T2 and if you're calling the WhoAmI method you have a receiver of type T by definition.




Your design might work better with an interface. Try something more like this:



type T interface {
WhoAmI() string
}

type T1 struct {
s string
}


func (t *T1) WhoAmI() string { return "T1" }

type T2 struct {
s string
}

func (t *T2) WhoAmI() string { return "T2" }


Try it on the Go playground




T1 and T2 both implement the interface T, so they can be used as type T.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...