为什么不能为结构体和它的指针同时定义一个方法?

huangapple go评论132阅读模式
英文:

Why can't a method be defined both for a struct and its pointer?

问题

给定golang tour的第54张幻灯片中的设置:

  1. type Abser interface {
  2. Abs() float64
  3. }
  4. type Vertex struct {
  5. X, Y float64
  6. }
  7. func (v *Vertex) Abs() float64 {
  8. return math.Sqrt(v.X*v.X + v.Y*v.Y)
  9. }

为什么方法不能同时为结构体和指向结构体的指针定义?即:

  1. func (v Vertex) Abs() float64 {
  2. return math.Sqrt(v.X*v.X + v.Y*v.Y)
  3. }

定义这个会产生以下错误:

  1. prog.go:41: method redeclared: Vertex.Abs
  2. method(*Vertex) func() float64
  3. method(Vertex) func() float64
英文:

Given the setup in the 54th slide of the golang tour:

  1. type Abser interface {
  2. Abs() float64
  3. }
  4. type Vertex struct {
  5. X, Y float64
  6. }
  7. func (v *Vertex) Abs() float64 {
  8. return math.Sqrt(v.X*v.X + v.Y*v.Y)
  9. }

Why can't a method also be defined for the struct as well as the pointer to the struct? That is:

  1. func (v Vertex) Abs() float64 {
  2. return math.Sqrt(v.X*v.X + v.Y*v.Y)
  3. }

Defining this gives the following error:

  1. prog.go:41: method redeclared: Vertex.Abs
  2. method(*Vertex) func() float64
  3. method(Vertex) func() float64

答案1

得分: 11

它可以。只需在结构体上定义它,而不是指针。它将双向解析。

方法集
> 相应指针类型 *T 的方法集是所有具有接收器 *T 或 T 的方法的集合(也就是说,它还包含 T 的方法集)

尝试运行:http://play.golang.org/p/PsNUerVyqp

  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. )
  6. type Abser interface {
  7. Abs() float64
  8. }
  9. type Vertex struct {
  10. X, Y float64
  11. }
  12. func (v Vertex) Abs() float64 {
  13. return math.Sqrt(v.X*v.X + v.Y*v.Y)
  14. }
  15. func main() {
  16. v := Vertex{5, 10}
  17. v_ptr := &v
  18. fmt.Println(v.Abs())
  19. fmt.Println(v_ptr.Abs())
  20. }

更新: 根据评论,我创建了一个额外的示例,实际上使用了 Abser 接口来说明值和指针都满足接口。

https://play.golang.org/p/Mls0d7_l4_t

英文:

It can. Just define it on the struct and not the pointer. It will resolve both ways

Method Sets
> The method set of the corresponding pointer type *T is the set of all
> methods with receiver *T or T (that is, it also contains the method
> set of T)

Try live: http://play.golang.org/p/PsNUerVyqp

  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. )
  6. type Abser interface {
  7. Abs() float64
  8. }
  9. type Vertex struct {
  10. X, Y float64
  11. }
  12. func (v Vertex) Abs() float64 {
  13. return math.Sqrt(v.X*v.X + v.Y*v.Y)
  14. }
  15. func main() {
  16. v := Vertex{5, 10}
  17. v_ptr := &v
  18. fmt.Println(v.Abs())
  19. fmt.Println(v_ptr.Abs())
  20. }

Update: As per comments I have created an extra example that actually makes use of the Abser interface to illustrate that both the value and the pointer satisfy the interface.

https://play.golang.org/p/Mls0d7_l4_t

答案2

得分: 4

在考虑以下示例时:

  1. type T U
  2. func (t *T) M() int { return 1 }
  3. var t T

...我们现在可以通过写入t.M()来调用t上的M(),因为语言允许在其基础(非指针)类型的实例上调用具有指针接收器的方法,即它等同于(&t).M()

如果现在允许额外定义:

  1. func (t T) M() int { return 2 }

...那么无法确定现在的t.M()应该返回什么。

英文:

While considering for example:

  1. type T U
  2. func (t *T) M() int { return 1 }
  3. var t T

...we can now invoke M() on t by writing t.M() as the language permits to call a method with a pointer receiver even on its underlying (non pointer) typed instances, i.e. it becomes equivalent to (&t).M().

If it will be permitted to now additionaly define:

  1. func (t T) M() int { return 2 }

...then there's no way to tell what is now t.M() supposed to return.

huangapple
  • 本文由 发表于 2012年11月11日 05:07:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/13326099.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定