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

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

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

问题

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

type Abser interface {
	Abs() float64
}

type Vertex struct {
	X, Y float64
}

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

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

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

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

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

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

type Abser interface {
	Abs() float64
}

type Vertex struct {
	X, Y float64
}

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

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

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

Defining this gives the following error:

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

答案1

得分: 11

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

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

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

package main

import (
	"fmt"
	"math"
)

type Abser interface {
	Abs() float64
}

type Vertex struct {
	X, Y float64
}

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

func main() {
	v := Vertex{5, 10}
	v_ptr := &v
	fmt.Println(v.Abs())
	fmt.Println(v_ptr.Abs())
}

更新: 根据评论,我创建了一个额外的示例,实际上使用了 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

package main

import (
	"fmt"
	"math"
	)

type Abser interface {
	Abs() float64
}

type Vertex struct {
	X, Y float64
}

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

func main() {
	v := Vertex{5, 10}
	v_ptr := &v
	fmt.Println(v.Abs())
	fmt.Println(v_ptr.Abs())
}

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

在考虑以下示例时:

type T U

func (t *T) M() int { return 1 }

var t T

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

如果现在允许额外定义:

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

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

英文:

While considering for example:

type T U

func (t *T) M() int { return 1 }

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:

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:

确定