实际上,在您的示例
ShapeInterface.PrintArea()中,对于a而言,调用工作正常,
Circle因为您
PrintArea()为该类型创建了一个方法
Circle。由于您没有
PrintArea()为
Rectangle类型创建,因此
Shape将调用嵌入式类型的方法。
这不是错误,这是预期的工作。Go 不是(相当)一种面向对象的语言:它没有类,也没有类型继承。但它支持类似的构造,称为在层和层上
嵌入
,并且确实具有方法。
struct``interface
您所期望的被称为 虚拟方法
:您期望该
PrintArea()方法将调用“重写”
Area()方法,但是在Go中没有继承和虚拟方法。
的定义
Shape.PrintArea()是调用
Shape.Area(),这就是发生的情况。
Shape不知道它是哪个结构以及是否嵌入其中,因此它无法将方法调用“分派”到虚拟的运行时方法。
的围棋语言规范:选择器描述的评价时,其遵循确切规则
x.f表达(其中,
f可以是方法)选择哪种方法,将在结束时调用。关键点:
*选择器
f可以表示一个字段或方法f的类型的T,或者它可以指字段或方法f嵌套的匿名字段的T。走过来达到匿名的字段数f被称为其
深度 在T。
* 对于值x类型的T或*T其中T不是指针或接口类型,x.f表示在最浅深度域或方法T,其中有这样一个f。
深入细节
圈
在以下情况下
Circle:
si.PrintArea()会叫
Circle.PrintArea(),因为你创造了这样的方法:
func (c *Circle) PrintArea() { fmt.Printf("%s : Area %vrn", c.GetName(), c.Area())}在此方法
c.Area()中,称为where
c是a
*Circle,因此
*Circle将调用存在接收者的方法。
PrintArea(si)来电
si.Area()。由于
si是,
Circle并且有一个
Area()带有
Circle接收方的方法,因此调用它没有问题。
长方形
在情况下,
Rectangle
si.PrintArea()实际上会调用该方法,
Shape.PrintArea()因为您
没有
PrintArea()为该
Rectangle类型定义一个方法(receive方法没有任何方法
*Rectangle)。和执行
Shape.PrintArea()方法调用
Shape.Area()
没有
Rectangle.Area()-作为讨论,
Shape不知道
Rectangle。所以你会看到
Rectangle1 : Area 0
印刷而不是预期
Rectangle1 : Area 20。
但是,如果您调用
PrintArea(si)(传递了
Rectangle),则会调用
si.Area(),这是
Rectangle.Area()因为该方法存在。



