英文:
Go: Is *Var a "subclass" of Var?
问题
第一个示例中,func (v *Vertex) Abs() float64 是指针接收器方法,而第二个示例中,func (v Vertex) Abs() float64 是值接收器方法。在Go语言中,接口的方法集由值接收器方法组成。因此,第一个示例中的*Vertex类型实现了Abser接口,而第二个示例中的Vertex类型也实现了Abser接口。这就是为什么第二个示例可以编译通过的原因。
英文:
taken from the go tour:
package main
import (
"fmt"
"math"
)
type Abser interface {
Abs() float64
}
func main() {
var a Abser
f := MyFloat(-math.Sqrt2)
v := Vertex{3, 4}
a = f
a = &v
// v == Vertex != *Vertex -> exception
a = v
}
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
type Vertex struct {
X, Y float64
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
However, when turning func (v *Vertex) Abs() float64 into func (v Vertex) Abs() float64, the code compiles:
package main
import (
"math"
)
type Abser interface {
Abs() float64
}
func main() {
var a Abser
f := MyFloat(-math.Sqrt2)
v := Vertex{3, 4}
a = f
// Since *Vertex != Vertex, this shouldn't compile, should it?
a = &v
a = v
}
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
type Vertex struct {
X, Y float64
}
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
Why does the second example run?
答案1
得分: 4
类型*T不是T的子类,但是*T的方法集将继承T的方法:
任何其他类型T的方法集由所有以接收器类型T声明的方法组成。相应指针类型T的方法集是所有以接收器类型T或T声明的方法的集合(也就是说,它还包含T的方法集)。
因此,如果T符合特定的接口,那么*T也会符合。这就是为什么在你的示例中可以将*Vertex的值赋给Abser变量的原因。
英文:
The type *T is not a subclass of T, but *T's method set will inherit the methods of T:
> The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).
So if T conforms to a particular interface, then so will *T. That is why you could assign a *Vertex value to an Abser variable in your example.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论