当前位置: 首页 > 面试题库 >

去嵌入式结构调用子方法,而不是父方法

高锦
2023-03-14
问题内容

这里是带有接口,父结构和2个子结构的Go代码示例

package main

import (
    "fmt"
    "math"
)

// Shape Interface : defines methods
type ShapeInterface interface {
    Area() float64
    GetName() string
    PrintArea()
}

// Shape Struct : standard shape with an area equal to 0.0
type Shape struct {
    name string
}

func (s *Shape) Area() float64 {
    return 0.0
}

func (s *Shape) GetName() string {
    return s.name
}

func (s *Shape) PrintArea() {
    fmt.Printf("%s : Area %v\r\n", s.name, s.Area())
}

// Rectangle Struct : redefine area method
type Rectangle struct {
    Shape
    w, h float64
}

func (r *Rectangle) Area() float64 {
    return r.w * r.h
}

// Circle Struct : redefine Area and PrintArea method 
type Circle struct {
    Shape
    r float64
}

func (c *Circle) Area() float64 {
    return c.r * c.r * math.Pi
}

func (c *Circle) PrintArea() {
    fmt.Printf("%s : Area %v\r\n", c.GetName(), c.Area())
}

// Genreric PrintArea with Interface
func  PrintArea (s ShapeInterface){
    fmt.Printf("Interface => %s : Area %v\r\n", s.GetName(), s.Area())
}

//Main Instruction : 3 Shapes of each type
//Store them in a Slice of ShapeInterface
//Print for each the area with the call of the 2 methods
func main() {

    s := Shape{name: "Shape1"}
    c := Circle{Shape: Shape{name: "Circle1"}, r: 10}
    r := Rectangle{Shape: Shape{name: "Rectangle1"}, w: 5, h: 4}

    listshape := []c{&s, &c, &r}

    for _, si := range listshape {
        si.PrintArea() //!! Problem is Witch Area method is called !! 
        PrintArea(si)
    }

}

我有结果:

$ go run essai_interface_struct.go
Shape1 : Area 0
Interface => Shape1 : Area 0
Circle1 : Area 314.1592653589793
Interface => Circle1 : Area 314.1592653589793
Rectangle1 : Area 0
Interface => Rectangle1 : Area 20

我的问题是对Circle和Rectangle调用Shape.PrintArea哪种调用Shape.Area方法,而不是调用Circle.AreaRectangle.Area方法。

这是Go中的错误吗?

谢谢你的帮助。


问题答案:

实际上,在您的示例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

深入细节

在以下情况下Circlesi.PrintArea()会叫Circle.PrintArea(),因为你创造了这样的方法:

func (c *Circle) PrintArea() {
    fmt.Printf("%s : Area %v\r\n", 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()因为该方法存在。



 类似资料:
  • 问题内容: 我正在尝试学习Go,并且在这里找到了很好的资源。 下面给出了有关方法重载的示例: 是否可以调用“基本”结构的(人类)方法,例如。sam.Human.SayHi()向下转换不起作用(因为没有正确的类型层次结构?) 问题答案: 您可以通过使用嵌入类型名称的名称调用父级成员来访问父级结构的嵌入结构。那是一个大嘴巴,所以可能更容易证明它。 产出

  • 问题内容: 让我们看一下这段代码: 我希望这能打印出“孩子”,但结果是“父母”。为什么Java会改为调用父类,我该怎么做才能使其在子类中调用方法? 问题答案: 不会覆盖,因为它没有相同的形式参数。一个拿走,另一个拿走。因此,运行时的多态不会被应用,并且不会导致子类方法的执行。根据Java语言规范: 如果满足以下所有条件,则在类C中声明或由类C继承的实例方法从类C中 重写 另一个在类A中声明的方法:

  • 问题内容: 对此有些困惑。请看游乐场。 我希望go允许您调用一个方法,该方法将一个父级与嵌入该父级的子级一起使用。 如果我使用“ child.Parent”来调用它,那么它可以工作,但是在那种情况下,我不能在函数中使用任何将值用作空接口的代码。对此进行了Google搜索,发现了一个非常有趣且有用的页面。 从OOP的角度看Golang的概念。欢迎就我在这里缺少的内容提供任何指导。也许这只是我在这里没

  • 我有两个组成部分: 父组件 子组件 我试图从Parent调用child的方法,我尝试了这种方法,但无法得到结果: 有没有办法从父级调用子级的方法? 注意:子组件和父组件在两个不同的文件中。

  • 问题内容: 我有两个组成部分。 父组件 子组件 我试图从父级调用孩子的方法,我尝试过这种方法,但没有得到结果 有没有一种方法可以从父级调用子级的方法? 注意:子组件和父组件位于两个不同的文件中 问题答案: 首先,让我表示,这通常 不是 在React领域中解决问题的方法。通常,您要做的是将功能传递给道具中的子代,并传递事件中的子代的通知(或者更好的是:)。 但是,如果 必须 在子组件上公开命令式方法

  • 问题内容: 我有一个父类A,及其子B。两者都具有带有diff类型参数的方法。 A级 B级 运行此命令时,将获得“ Base impl:override”作为输出! 指向的对象,而他经过的说法是,所以不应该调用它的方法是什么? 问题答案: 当您使用类型A的引用时,您只会看到为类A定义的方法。由于B中不会覆盖B(因为它具有不同的签名),因此不会调用它。 如果要使用类型B的引用,则两种方法都将可用,并且