Golang中接口与抽象类型的探讨及应用

Golang中接口与抽象类型的探讨及应用 为什么这段代码没有为所有通过嵌入 Shape "抽象"类型实现 Shaper 接口的对象输出面积值 1?

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

我正在尝试完成《The Way to Go》中的练习 11.2.3。遗憾的是书中没有提供参考答案。题目要求如下: “现在我们将通过使用’抽象’类型 Shape(之所以称为抽象是因为它没有字段)来实现相同的功能,该类型实现了 Shaper 接口,并将其嵌入到其他类型中。请演示 §10.6.5 中解释的重写机制:interfaces_poly3.go”


更多关于Golang中接口与抽象类型的探讨及应用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

我为你简化了之前的示例,以便理解其工作原理。

package main

type Shape struct {}

type Rectangle struct {
    Shape
}

func (r Rectangle) Area() {
    println(1)
}

func (s Shape) Area() {
    println(2)
}

func main() {
    var s Shape
    r := Rectangle{s}
    r.Area()
    r.Shape.Area()
}

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

更多关于Golang中接口与抽象类型的探讨及应用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,接口的实现是隐式的,但通过嵌入类型实现接口时需要注意方法重写机制。让我分析一下你提供的代码问题,并给出修正版本。

问题分析

原代码的问题在于:

  1. Shape 类型实现了 Shaper 接口的 Area() 方法
  2. 当其他类型嵌入 Shape 时,如果没有重写 Area() 方法,就会使用 Shape 的默认实现
  3. ShapeArea() 方法返回固定值 1,导致所有未重写该方法的类型都输出 1

修正代码

package main

import "fmt"

type Shaper interface {
    Area() float32
}

type Shape struct{}

// Shape 的默认 Area 实现
func (s Shape) Area() float32 {
    return 1.0
}

type Rectangle struct {
    Shape  // 嵌入 Shape
    length, width float32
}

// Rectangle 必须重写 Area 方法
func (r Rectangle) Area() float32 {
    return r.length * r.width
}

type Square struct {
    Shape  // 嵌入 Shape
    side float32
}

// Square 重写 Area 方法
func (s Square) Area() float32 {
    return s.side * s.side
}

type Circle struct {
    Shape  // 嵌入 Shape
    radius float32
}

// Circle 重写 Area 方法
func (c Circle) Area() float32 {
    return 3.14 * c.radius * c.radius
}

func main() {
    r := Rectangle{length: 5, width: 3}
    s := Square{side: 4}
    c := Circle{radius: 2}
    
    shapes := []Shaper{r, s, c}
    
    for _, shape := range shapes {
        fmt.Printf("Area: %f\n", shape.Area())
    }
}

关键要点

  1. 方法重写机制:当类型嵌入另一个类型时,外层类型可以重写内层类型的方法
  2. 接口实现:只要类型实现了接口的所有方法,就自动满足该接口
  3. 嵌入类型的作用Shape 作为抽象基类,提供默认行为,但具体类型应该重写相关方法

输出结果

Area: 15.000000
Area: 16.000000
Area: 12.560000

这样每个具体类型都正确计算了自己的面积,而不是都返回默认值 1。嵌入 Shape 类型的主要目的是展示Go语言中的组合和重写机制,而不是作为真正的抽象基类使用。

回到顶部