5.4.4 多态
现在了解了接口和方法集背后的机制,最后来看一个展示接口的多态行为的例子,如代码清单5-48所示。
代码清单5-48 listing48.go
01 // 这个示例程序使用接口展示多态行为
02 package main
03
04 import (
05 "fmt"
06 )
07
08 // notifier是一个定义了
09 // 通知类行为的接口
10 type notifier interface {
11 notify()
12 }
13
14 // user在程序里定义一个用户类型
15 type user struct {
16 name string
17 email string
18 }
19
20 // notify使用指针接收者实现了notifier接口
21 func (u *user) notify() {
22 fmt.Printf("Sending user email to %s<%s>\n",
23 u.name,
24 u.email)
25 }
26
27 // admin定义了程序里的管理员
28 type admin struct {
29 name string
30 email string
31 }
32
33 // notify使用指针接收者实现了notifier接口
34 func (a *admin) notify() {
35 fmt.Printf("Sending admin email to %s<%s>\n",
36 a.name,
37 a.email)
38 }
39
40 // main是应用程序的入口
41 func main() {
42 // 创建一个user值并传给sendNotification
43 bill := user{"Bill", "bill@email.com"}
44 sendNotification(&bill)
45
46 // 创建一个admin值并传给sendNotification
47 lisa := admin{"Lisa", "lisa@email.com"}
48 sendNotification(&lisa)
49 }
50
51 // sendNotification接受一个实现了notifier接口的值
52 // 并发送通知
53 func sendNotification(n notifier) {
54 n.notify()
55 }
在代码清单5-48中,我们有了一个展示接口的多态行为的例子。在第10行,我们声明了和之前代码清单中一样的 notifier
接口。之后第15行到第25行,我们声明了一个名为 user
的结构,并使用指针接收者实现了 notifier
接口。在第28行到第38行,我们声明了一个名为 admin
的结构,用同样的形式实现了 notifier
接口。现在,有两个实体类型实现了 notifier
接口。
在第53行中,我们再次声明了多态函数 sendNotification
,这个函数接收一个实现了 notifier
接口的值作为参数。既然任意一个实体类型都能实现该接口,那么这个函数可以针对任意实体类型的值来执行 notifier
方法。因此,这个函数就能提供多态的行为,如代码清单5-49所示。
代码清单5-49 listing48.go:第40行到第49行
40 // main是应用程序的入口
41 func main() {
42 // 创建一个user值并传给sendNotification
43 bill := user{"Bill", "bill@email.com"}
44 sendNotification(&bill)
45
46 // 创建一个admin值并传给sendNotification
47 lisa := admin{"Lisa", "lisa@email.com"}
48 sendNotification(&lisa)
49 }
最后,可以在代码清单5-49中看到这种多态的行为。 main
函数的第43行创建了一个 user
类型的值,并在第44行将该值的地址传给了 sendNotification
函数。这最终会导致执行 user
类型声明的 notify
方法。之后,在第47行和第48行,我们对 admin
类型的值做了同样的事情。最终,因为 sendNotification
接收 notifier
类型的接口值,所以这个函数可以同时执行 user
和 admin
实现的行为。