接口简介
本课属于 Coddy GO 学习旅程的“面向对象编程”单元。第 25 课,共 107 课。
Go 中的接口定义一组方法签名,但不实现这些方法。它描述的是一种类型能做什么,而不是它如何实现。如果某种类型实现了接口中的所有方法,就会自动满足该接口。
下面介绍如何定义接口:
type Speaker interface {
Speak() string
}这个 Speaker 接口要求任何实现它的类型都必须有一个返回字符串的 Speak() 方法。现在,任何具有此方法的结构体都可以在需要 Speaker 的地方使用。
type Dog struct {
Name string
}
func (d Dog) Speak() string {
return d.Name + " says woof!"
}
type Cat struct {
Name string
}
func (c Cat) Speak() string {
return c.Name + " says meow!"
}Dog 和 Cat 都满足 Speaker 接口,因为它们各自都有一个签名正确的 Speak() 方法。现在,你可以编写接受任意 Speaker 的函数:
func MakeSound(s Speaker) {
fmt.Println(s.Speak())
}
func main() {
dog := Dog{Name: "Buddy"}
cat := Cat{Name: "Whiskers"}
MakeSound(dog) // Buddy 说:汪汪!
MakeSound(cat) // Whiskers 说:喵喵!
}接口能让你编写灵活、可复用的代码,只要某种类型满足接口的要求,无论其底层实现如何,这些代码都能正常工作。
挑战
简单让我们构建一个车辆描述系统,展示接口如何让不同类型共享相同的行为。你将创建一个多个车辆类型都能满足的接口,然后用它统一描述任何车辆。
你需要将代码分成两个文件:
vehicles.go:定义一个只有一个方法Describe() string的Describer接口。然后创建两个满足此接口的结构体:Car,包含Brand和Model字段(两者都是字符串)Bicycle,包含Type(字符串)和Gears(整数)字段
Describe()方法,用于返回描述车辆的字符串。main.go:创建一个名为PrintDescription的函数,它接收任意Describer,并打印调用其Describe()方法的结果。从输入中读取车辆信息,创建一个 Car 和一个 Bicycle,并使用你的函数分别打印它们的描述。
将提供以下输入:
- 第 1 行:汽车品牌
- 第 2 行:汽车型号
- 第 3 行:自行车类型
- 第 4 行:齿轮数量(整数)
你的 Describe() 方法应按以下格式返回字符串:
- Car:
[Brand] [Model] - Bicycle:
[Type] bike with [Gears] gears
例如,输入 Toyota、Camry、Mountain 和 21 时,输出应为:
Toyota Camry
Mountain bike with 21 gears关键在于,你的 PrintDescription 函数可以处理任何具有 Describe() 方法的类型。它不需要知道自己处理的是 Car、Bicycle,还是你以后可能添加的其他车辆类型。
亲手试试
package main
import (
"fmt"
)
// TODO: 创建一个接受任意 Describer 的 PrintDescription 函数
// 并打印调用其 Describe() 方法的结果
func main() {
// 读取输入
var carBrand string
var carModel string
var bicycleType string
var gears int
fmt.Scanln(&carBrand)
fmt.Scanln(&carModel)
fmt.Scanln(&bicycleType)
fmt.Scanln(&gears)
// TODO: 使用输入的品牌和型号创建一个 Car
// TODO: 使用输入的类型和挡位数创建一个 Bicycle
// TODO: 使用 PrintDescription 打印汽车的描述
// TODO: 使用 PrintDescription 打印自行车的描述
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Go 在线编译器