英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论