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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With