为什么即使结构指针没有实现接口,我们也可以将结构指针分配给接口变量? [英] Why can we assign a struct pointer to an interface variable even though the struct pointer does not implement the interface?

查看:114
本文介绍了为什么即使结构指针没有实现接口,我们也可以将结构指针分配给接口变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在下面介绍了两个程序:程序1和程序2.

I present two programs below: program 1 and program 2.

我希望程序1无法编译,并且确实无法编译.这样很好.

I expect program 1 to fail to compile and it indeed fails to compile. So that's good.

我希望程序2无法编译,但可以成功!这个问题是关于程序2成功的原因.

I expect program 2 to fail to compile but it succeeds! This question is about why program 2 succeeds.

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

package main

import (
    "fmt"
    "math"
)

type Abser interface {
    Abs() float64
}

type Vertex struct {
    X float64
    Y float64
}

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

func main() {
    var a Abser
    
    a = Vertex{3, 4}
    fmt.Println(a.Abs())
}

无法通过此错误进行编译:

This fails to compile with this error:

./prog.go:24:4: cannot use Vertex literal (type Vertex) as type Abser in assignment:
Vertex does not implement Abser (Abs method has pointer receiver)

我之所以期望出现此错误,是因为*Vertex实现了Abser,但Vertex没有实现,因此我们无法将Vertex对象分配给Abser变量.

I was expecting this error because *Vertex implements Abser but Vertex does not, so we cannot assign a Vertex object to an Abser variable.

https://play.golang.org/p/4bIs-fHGhYm

package main

import (
    "fmt"
    "math"
)

type Abser interface {
    Abs() float64
}

type Vertex struct {
    X float64
    Y float64
}

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

func main() {
    var a Abser
    
    a = &Vertex{3, 4}
    fmt.Println(a.Abs())
}

这将成功编译.该程序的输出为:

This compiles successfully. The output of the program is:

5

为什么成功?在这里,Vertex实现Abser,但是*Vertex不实现Abser.然后如何为Abser分配类型为*Vertex的值?

Why did this succeed? Here, Vertex implements Abser but *Vertex does not implement Abser. How am I then able to assign a value of type *Vertex to Abser?

要知道为什么成功,我需要了解哪些语言语义规则?

What are the language semantic rules I need to understand to know why this succeeds?

推荐答案

可分配性要求阐明接口情况下所需的内容:

The assignability requirements spell out what is needed in the case of interfaces:

值x可分配给类型T的变量("x可分配给类型" T)如果满足以下条件之一:

A value x is assignable to a variable of type T ("x is assignable to T") if one of the following conditions applies:

... T是接口类型,并且x实现T. ...

... T is an interface type and x implements T. ...

为了确定"x实现T"的规则,我们转向方法集的概念:

To determine the rules of "x implements T", we turn to the concept of method sets:

类型可能具有与之关联的方法集.方法集 接口类型是它的接口.任何其他类型T的方法集 包含以接收方类型T声明的所有方法.

A type may have a method set associated with it. The method set of an interface type is its interface. The method set of any other type T consists of all methods declared with receiver type T.

乍看之下,这意味着第一个示例中的Vertex方法集为空,而第二个示例中的*Vertex方法集也为空.

At first glance, this means that the method set of Vertex in your first example is empty, and the method set of *Vertex in your second example is also empty.

但是,规范会继续指定:

However, the spec goes on to specify:

对应的指针类型* T的方法集是全部的集合 用接收者* T或T声明的方法(也就是说,它还包含 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).

这意味着方法集*Vertex自动包含Vertex的方法集,而不是相反的方法.

This means that the method set of *Vertex automatically includes the method set of Vertex, but not the other way around.

这在您的第一个示例中无济于事,但是在第二个示例中,Vertex的方法集确实包含了Abs() float64.由于这是实现Abser接口所需的全部,因此*Vertex被视为实现Abser.

This does not help in your first example, but in the second example the method set of Vertex does include Abs() float64. Since this is all that is required to implement the Abser interface, *Vertex is deemed to implement Abser.

这篇关于为什么即使结构指针没有实现接口,我们也可以将结构指针分配给接口变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆