2011-06-26 37 views
4

如果type T2基于type T1,除了共享相同的数据字段,T1T2之间是否有任何关系?在Go中,如果T2类型基于T1类型,是否有任何类型的从T1到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) 
} 

这里我的理解是缺乏

  1. 一直希望T2将继承T1的方法,但这种情况并非如此。

  2. 期待T2可以强迫T1,因为它是从T1

  3. 衍生感到惊讶的是T1可以强迫T2,但事实如此。

  4. 看来T1T2之间的关系是完全对称的 - 尽管实际上是从另一个实际导出的,但我无法找到任何破坏对称性的东西 - 或者这是幻觉?

(注:我不批评或判断 - 我完全尊重做出的决定 - 只是验证我明白了什么是那里,对我来说是反直觉的 - 我相信我不是唯一一个!)

回答

4

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

Is Go an object-oriented language?

Why is there no type inheritance?

的方法被绑定到单个特定的类型。

A method declaration将 标识符绑定到方法。该方法是 表示绑定到基类型,并且 仅在类型为 的选择器中可见。

你可以种T1T2之间convert

x可以converted键入 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) 
} 

Output: 
T1 T2 
T1 T2 
T1 T2 
+0

所以当你说'输入T2 T1'时,发生了什么事情是'T1'的结构被复制为'T2'的结构,并且它们具有相同的结构,它们可以重新对换,否则'T2'与'T1'没有任何关系 –

+0

是的。有很多转换规则。对于这个特定的规则,“T1”和“T2”具有相同的底层类型这一事实意味着它们也具有相同的内存大小,布局和内容。 – peterSO

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

的作品,因为你投它键入T2,因此它允许F2。所以它有望运作。 F2函数然后在您的T2对象t1上调用,该对象返回t1.s

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

对于这一块,我不能告诉你肯定的,但只能给你我的想法可行,以及:

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

另请参阅Go for C++ programmers,其中规定:

方法是在命名类型定义。如果将该值转换为其他类型,则新值将具有新类型的方法,而不是旧类型。

0

我可以解释为什么T2没有方法T1。想象一下,你需要用两种不同的方式对T类型的数据进行排序。一种方法是默认设置,因此您在T中实施Len,LessSwap方法。您可以拨打sort.Sort(data)并以默认方式对数据进行排序。但如何对数据进行不同的分类?

您编写type SortDifferently T并执行Len,LessSwap方法为SortDifferently类型。如果SortDifferently的所有方法都是T,则不能这样做,因为Go没有方法重写。但是,如果没有继承,您现在可以编写sort.Sort((SortDifferently)data)以不同方式对数据进行排序。

这是Go的做事方式。习惯并不容易。

+0

“Go没有方法覆盖” - 我想这就是了。 –

+0

事情是Go * does *有方法阴影。如果使用'SortDifferently struct {T}',它会将所有方法从'T'转发到'SortDifferently',并且仍允许您使用专门在'SortDifferently'上编写的方法来映射这些名称。您仍然可以调用“T”版本,即使在影子方法中也是如此。我不知道他们为什么不接受'SortDifferently T'类型的情况。 – matthias

0

不知道它是否会帮助你,但看看例如"Go for C++ programmers",在“接口”部分描述的“匿名字段” - 看起来他们提供了一些看起来像子类的东西。

但无论如何,通过Go上的教程阅读,我开发了一个想法,Go的作者决定让程序员避开构建继承链并改用嵌入/委派。

相关问题