英文:
If type T2 is based on type T1, is there any sort of "inheritance" from T1 to T2?
问题
如果type T2
是基于type T1
的,除了共享相同的数据字段之外,T1
和T2
之间是否有任何关系?
我的理解在这里有所欠缺
-
希望
T2
能继承T1
的方法,但事实并非如此。 -
希望
T2
可以被强制转换为T1
,因为它是从T1
派生出来的。 -
惊讶的是,
T1
可以被强制转换为T2
,但事实如此。 -
看起来
T1
和T2
之间的关系是完全对称的 - 尽管一个实际上是从另一个派生出来的,但我找不到任何打破对称性的东西 - 或者这是一种错觉吗?
英文:
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
-
was hoping that
T2
would inheritT1
's methods, but such is not the case. -
was expecting
T2
could be coerced intoT1
, since it was derived fromT1
-
was surprised that
T1
could be coerced intoT2
, but so it is. -
it seems that the relationship between
T1
andT2
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不支持面向对象的类型继承。
一个方法绑定到一个特定的类型。
> 方法声明将标识符绑定到一个方法。该方法被绑定到基本类型,并且只在该类型的选择器中可见。
你可以在类型T1
和T2
之间进行转换。
> 当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 (
"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
答案2
得分: 1
我可以解释为什么T2
没有T1
的方法。想象一下,你需要以两种不同的方式对类型为T
的一些数据进行排序。一种方式是默认的,所以你在T
中实现了Len
、Less
和Swap
方法。你可以调用sort.Sort(data)
以默认方式对数据进行排序。但是如何以不同的方式对数据进行排序呢?
你可以编写type SortDifferently T
,并为SortDifferently
类型实现Len
、Less
和Swap
方法。如果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)(&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 "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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论