Reputation: 20255
If type T2
is based on type T1
, other than sharing the same data fields, is there any relationship between T1
and T2
?
package main import "fmt" type T1 struct { s string } func (v *T1) F1() string { return v.s } type T2 T1 func (v *T2) F2() string { return v.s } func main() { var t1 = T1{ "xyz" } var t2 = T2{ "pdq" } s0 := t2.F1() // error - expected ok s1 := ((*T1)(&t2)).F1() // ok - expected s2 := ((*T2)(&t1)).F2() // ok - not expected fmt.Println( s0, s1, s2 ) }
My understanding here is lacking
was hoping that T2
would inherit T1
's methods, but such is not the case.
was expecting T2
could be coerced into T1
, since it was derived from T1
was surprised that T1
could be coerced into T2
, but so it is.
it seems that the relationship between T1
and T2
is completely symmetrical - I cannot find anything that breaks the symmetry despite the fact one is actually derived from the other - or is this an illusion?
Upvotes: 12
Views: 1888
Reputation: 1
For another option, you can use embedding:
package main
import "fmt"
type T1 struct { s string }
func (v *T1) F1() string { return v.s }
type T2 struct { T1 }
func (v *T2) F2() string { return v.s }
func main() {
a := new(T1).F1()
// undefined (type *T1 has no field or method F2)
// b := new(T1).F2()
c := new(T2).F1()
d := new(T2).F2()
fmt.Print(a, c, d)
}
https://golang.org/ref/spec#Struct_types
Upvotes: 0
Reputation: 166925
Go does not support object-oriented type inheritance.
Is Go an object-oriented language?
Why is there no type inheritance?
A method is bound to a single specific type.
A method declaration binds an identifier to a method. The method is said to be bound to the base type and is visible only within selectors for that type.
You can convert between types T1
and T2
.
A value
x
can be converted to typeT
[when]x
's type andT
have identical underlying types.
For example,
package main
import (
"fmt"
)
type T1 struct{ i int }
func (t T1) String() string { return "T1" }
type T2 T1
func (t T2) String() string { return "T2" }
func main() {
t1 := T1{1}
t2 := T2{2}
fmt.Println(t1, t2)
c1 := T1(t2)
c2 := T2(t1)
fmt.Println(c1, c2)
t1 = T1(c2)
t2 = T2(c1)
fmt.Println(t1, t2)
}
Output:
T1 T2
T1 T2
T1 T2
Upvotes: 11
Reputation: 55573
Not sure if it'll help you but look at the "anonymous fields" described for instance in "Go for C++ programmers", under the "Interfaces" section -- it appears they provide something looking like child classes.
But in any case, reading through tutorials on Go, I developed an idea that Go's authors decidedly wanted programmers to steer away from building inheritance chains and use embedding/delegation instead.
Upvotes: 1
Reputation: 3454
I can explain why T2
doesn't have methods of T1
. Imagine that you need to sort some data of type T
in two different ways. One way is default and so you implement Len
, Less
and Swap
methods in T
. You can call sort.Sort(data)
and sort data in default way. But how to sort data differently?
You write type SortDifferently T
and implement Len
, Less
and Swap
methods for type SortDifferently
. If SortDifferently
had all methods of T
, you couldn't do that because Go doesn't have methods overrides. But without inheritance you can now write sort.Sort((SortDifferently)data)
to sort data in different way.
This is a Go way of doing things. It is not easy to get used to.
Upvotes: 1
Reputation: 9247
s2 := ((*T2)(&t1)).F2() // ok - not expected
works because you cast it to type T2
, and it thus allows F2
. So it is expected to work. The F2
function is then called on your T2
object t1
which returns t1.s
.
s0 := t2.F1() // error - expected ok
For this one, I can not tell you for sure but only give you my plausible idea as well:
F1 is a method on type T1. As t2 is not of type T1 you can not call F1 on t2. So, as you noted, only data-fields are shared, not the methods on those types.
Also see Go for C++ programmers, which states:
Methods are defined on named types. If you convert the value to a different type, the new value will have the methods of the new type, not the old type.
Upvotes: 0