如果类型T2基于类型T1,那么从T1到T2是否存在某种形式的“继承”?

huangapple go评论104阅读模式
英文:

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

问题

如果type T2是基于type T1的,除了共享相同的数据字段之外,T1T2之间是否有任何关系?

我的理解在这里有所欠缺

  1. 希望T2能继承T1的方法,但事实并非如此。

  2. 希望T2可以被强制转换为T1,因为它是从T1派生出来的。

  3. 惊讶的是,T1可以被强制转换为T2,但事实如此。

  4. 看起来T1T2之间的关系是完全对称的 - 尽管一个实际上是从另一个派生出来的,但我找不到任何打破对称性的东西 - 或者这是一种错觉吗?

英文:

If type T2 is based on type T1, other than sharing the same data fields, is there any relationship between T1 and T2?
<pre>
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 )
}
</pre>

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?

答案1

得分: 11

Go不支持面向对象的类型继承。

Go是一种面向对象的语言吗?

为什么没有类型继承?

一个方法绑定到一个特定的类型。

> 方法声明将标识符绑定到一个方法。该方法被绑定到基本类型,并且只在该类型的选择器中可见。

你可以在类型T1T2之间进行转换

> 当x的类型和T具有相同的底层类型时,值x可以被转换为类型T

例如,

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)
}

输出:
T1 T2
T1 T2
T1 T2
英文:

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 (
	&quot;fmt&quot;
)

type T1 struct{ i int }

func (t T1) String() string { return &quot;T1&quot; }

type T2 T1

func (t T2) String() string { return &quot;T2&quot; }

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

答案2

得分: 1

我可以解释为什么T2没有T1的方法。想象一下,你需要以两种不同的方式对类型为T的一些数据进行排序。一种方式是默认的,所以你在T中实现了LenLessSwap方法。你可以调用sort.Sort(data)以默认方式对数据进行排序。但是如何以不同的方式对数据进行排序呢?

你可以编写type SortDifferently T,并为SortDifferently类型实现LenLessSwap方法。如果SortDifferently拥有T的所有方法,你就无法这样做,因为Go语言没有方法重写。但是在没有继承的情况下,你现在可以编写sort.Sort((SortDifferently)data)以不同的方式对数据进行排序。

这是Go语言的做事方式。要习惯起来并不容易。

英文:

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.

答案3

得分: 1

不确定它是否对你有帮助,但可以看一下在《Go for C++ programmers》中描述的“匿名字段”,在“接口”部分中有介绍 - 看起来它们提供了类似子类的功能。

但无论如何,在阅读关于Go的教程时,我得出了一个想法,即Go的作者明确希望程序员避免构建继承链,而是使用嵌入/委托。

英文:

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.

答案4

得分: 0

s2 := ((*T2)(&t1)).F2() // ok - not expected

因为你将其转换为类型T2,所以它允许F2。所以这是可以预期的。然后在你的T2对象t1上调用F2函数,它返回t1.s

s0 := t2.F1() // error - expected ok

对于这个问题,我不能确定,只能给出我合理的想法:

F1是类型T1的方法。由于t2不是类型T1,所以不能在t2上调用F1。所以,正如你所指出的,只有数据字段是共享的,而不是这些类型上的方法。

另请参阅Go for C++ programmers,其中提到:

> 方法是在命名类型上定义的。如果将值转换为不同类型,新值将具有新类型的方法,而不是旧类型的方法。

英文:
s2 := ((*T2)(&amp;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.

答案5

得分: 0

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)
}

英文:

For another option, you can use embedding:

package main
import &quot;fmt&quot;

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>

huangapple
  • 本文由 发表于 2011年6月26日 21:19:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/6484172.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定