跳到主要内容

Go 多态

介绍

多态是面向对象编程中的一个重要概念,它允许不同的对象对同一消息做出不同的响应。在Go语言中,多态主要通过接口(interface)来实现。接口定义了一组方法签名,任何实现了这些方法的类型都可以被视为该接口的实现。通过这种方式,Go语言实现了多态性。

接口与多态

在Go语言中,接口是一种类型,它定义了一组方法签名。任何实现了这些方法的类型都可以被视为该接口的实现。通过接口,我们可以编写通用的代码,这些代码可以处理任何实现了该接口的类型。

定义接口

首先,我们定义一个接口 Shape,它包含一个方法 Area()

go
type Shape interface {
Area() float64
}

实现接口

接下来,我们定义两个结构体 CircleRectangle,并让它们实现 Shape 接口:

go
type Circle struct {
Radius float64
}

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

type Rectangle struct {
Width, Height float64
}

func (r Rectangle) Area() float64 {
return r.Width * r.Height
}

使用接口

现在,我们可以编写一个函数 PrintArea,它接受一个 Shape 接口类型的参数,并打印其面积:

go
func PrintArea(s Shape) {
fmt.Println("Area:", s.Area())
}

我们可以将 CircleRectangle 的实例传递给 PrintArea 函数:

go
func main() {
c := Circle{Radius: 5}
r := Rectangle{Width: 10, Height: 5}

PrintArea(c) // 输出: Area: 78.53981633974483
PrintArea(r) // 输出: Area: 50
}

在这个例子中,PrintArea 函数可以处理任何实现了 Shape 接口的类型,这就是多态的体现。

实际案例

图形绘制系统

假设我们正在开发一个图形绘制系统,系统需要支持多种图形(如圆形、矩形、三角形等)。我们可以定义一个 Drawable 接口,所有图形类型都实现这个接口:

go
type Drawable interface {
Draw()
}

然后,我们可以为每种图形类型实现 Draw 方法:

go
type Circle struct {
Radius float64
}

func (c Circle) Draw() {
fmt.Println("Drawing a circle with radius", c.Radius)
}

type Rectangle struct {
Width, Height float64
}

func (r Rectangle) Draw() {
fmt.Println("Drawing a rectangle with width", r.Width, "and height", r.Height)
}

最后,我们可以编写一个函数 RenderScene,它接受一个 Drawable 接口类型的切片,并依次调用每个元素的 Draw 方法:

go
func RenderScene(shapes []Drawable) {
for _, shape := range shapes {
shape.Draw()
}
}

通过这种方式,我们可以轻松地扩展系统以支持新的图形类型,而不需要修改 RenderScene 函数。

总结

多态是面向对象编程中的一个重要概念,它允许我们编写通用的代码,这些代码可以处理多种不同的类型。在Go语言中,多态主要通过接口来实现。通过定义接口并让不同的类型实现这些接口,我们可以实现多态性。

附加资源

练习

  1. 定义一个 Animal 接口,包含 Speak() 方法。然后定义 DogCat 结构体,并让它们实现 Animal 接口。编写一个函数 MakeSpeak,它接受一个 Animal 接口类型的参数,并调用其 Speak() 方法。

  2. 扩展图形绘制系统的例子,添加一个新的图形类型 Triangle,并实现 Drawable 接口。然后更新 RenderScene 函数以支持新的图形类型。