Go语言:为何*Vertex类型可调用Abs()?接口实现疑问
为什么
*Vertex能调用值接收者的Abs()方法? 嘿,这个问题问到点子上了!这其实是Go语言方法集自动适配的特性在背后起作用,咱们结合你的代码一步步理清楚:
首先看你的方法定义:
func (v Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) }
这里Abs()的接收者是值类型Vertex,不是指针类型*Vertex。那为什么a(类型是*Vertex)能调用它呢?
Go的方法集规则:指针自动解引用
Go语言有个很贴心的设计:当你使用指针类型的变量调用方法时,编译器会自动帮你做指针解引用。也就是说,当你写a.Abs()的时候,Go会偷偷把它转换成:
(*a).Abs()
而*a就是一个Vertex值,正好匹配Abs()的值接收者,所以方法能正常执行。
关于接口实现的补充
你提到“*Vertex并未实现Abs()方法”,其实从接口实现的角度来说,*Vertex是完全满足Abser接口的。因为Go里:
- 值类型
T的方法集只包含接收者为T的方法 - 指针类型
*T的方法集同时包含接收者为T和*T的方法
所以*Vertex的方法集里自然包含了Abs(),也就实现了Abser接口,这也是为什么你能把&v赋值给a(Abser类型变量)的原因。
反过来,如果Abs()是指针接收者,那值类型Vertex能不能调用它?其实也可以,Go会自动取地址(相当于(&v).Abs()),但如果是不可寻址的值(比如字面量Vertex{1,2})就不行啦。
内容的提问来源于stack exchange,提问作者Pei Hsiang Hung
相关产品推荐
相关产品推荐

