如果type T2
基于type 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 ) }
我的理解缺乏
希望T2
继承T1
的方法,但事实并非如此。
期待T2
被强制转换为T1
,因为它来自T1
感到惊讶的是,T1
可能被强制转移到T2
,但事实确实如此。
似乎T1
和T2
之间的关系是完全对称的 - 我找不到任何破坏对称性的东西,尽管事实上一个实际上来自另一个 - 或者这是一个幻觉?
(注意:我不批评或评判 - 我完全尊重做出的决定 - 只是验证我明白对我来说有什么反直觉 - 我敢肯定我不是只有一个!)
答案 0 :(得分:8)
Go不支持面向对象的类型继承。
Is Go an object-oriented language?
Why is there no type inheritance?
方法绑定到单个特定类型。
method declaration绑定一个 方法的标识符。方法是 据说要绑定基类型 仅在选择器中可见 那种类型。
您可以在T1
和T2
类型之间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
答案 1 :(得分:1)
不确定它是否会对你有所帮助,但是看看“{3}}中描述的”匿名字段“,在”接口“部分下 - 它们似乎提供了类似子类的东西。
但无论如何,通过Go上的教程阅读,我开发了一个想法,Go的作者肯定希望程序员避免构建继承链并使用嵌入/委派代替。
答案 2 :(得分: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,其中说明:
在命名类型上定义方法。如果将值转换为其他类型,则新值将具有新类型的方法,而不是旧类型。
答案 3 :(得分:0)
我可以解释为什么T2
没有T1
的方法。想象一下,您需要以两种不同的方式对T
类型的数据进行排序。一种方法是默认方式,因此您可以在Len
中实施Less
,Swap
和T
方法。您可以调用sort.Sort(data)
并以默认方式对数据进行排序。但是如何对数据进行不同的排序
您为type SortDifferently T
类型编写Len
并实施Less
,Swap
和SortDifferently
方法。如果SortDifferently
拥有T
的所有方法,则无法执行此操作,因为Go没有方法覆盖。但是如果没有继承,您现在可以编写sort.Sort((SortDifferently)data)
以不同的方式对数据进行排序。
这是Go的做事方式。要习惯它并不容易。
答案 4 :(得分: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)
}