cc young
cc young

Reputation: 20255

If type T2 is based on type T1, is there any sort of "inheritance" from T1 to T2?

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

  1. was hoping that T2 would inherit T1's methods, but such is not the case.

  2. was expecting T2 could be coerced into T1, since it was derived from T1

  3. was surprised that T1 could be coerced into T2, but so it is.

  4. 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

Answers (5)

Zombo
Zombo

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

peterSO
peterSO

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 type T [when] x's type and T 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

kostix
kostix

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

Ha.
Ha.

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

Kissaki
Kissaki

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

Related Questions