Ezreal 书架 Ezreal 书架
Home
  • 《Go程序员面试笔试宝典》
  • 《RabbitMQ 实战指南》
  • 《深入理解kafka》
  • MySQL45讲
  • 透视HTTP协议
  • 结构化数据的分布式存储系统
  • Raft 共识算法
Home
  • 《Go程序员面试笔试宝典》
  • 《RabbitMQ 实战指南》
  • 《深入理解kafka》
  • MySQL45讲
  • 透视HTTP协议
  • 结构化数据的分布式存储系统
  • Raft 共识算法
  • 逃逸分析

  • 延迟语句

  • 数据容器

  • 通道

  • 接口

    • Go 接口与 C++接口有何异同
    • Go 语言与“鸭子类型”的关系
    • iface 和 eface 的区别是什么
    • 值接收者和指针接收者的区别
    • 如何用 interface 实现多态
    • 接口的动态类型和动态值是什么
    • 接口转换的原理是什么
    • 类型转换和断言的区别是什么
    • 如何让编译器自动检测类型是否实现了接口
  • unsafe

  • context

  • Go程序员面试笔试宝典
  • 接口
ezreal_rao
2023-05-31

如何用 interface 实现多态

Go 语言并没有设计诸如虚函数、纯虚函数、继承、多重继承等概念,但它通过接口却非常优雅地支持了面向对象的特性。

多态是一种运行期的行为,它有以下几个特点:

1)一种类型具有多种类型的能力。
2)允许不同的对象对同一消息做出灵活的反应。
3)以一种通用的方式对待个使用的对象。
4)非动态语言必须通过继承和接口的方式来实现。

来看一个实现了多态的例子:

package main

import "fmt"

func main() {
	qcrao := Student{age: 18}
	whatJob(&qcrao)
	growUp(&qcrao)
	fmt.Println(qcrao)
	stefno := Programmer{age: 100}
	whatJob(stefno)
	growUp(stefno)
	fmt.Println(stefno)
}

func whatJob(p Person) {
	p.job()
}

func growUp(p Person) {
	p.growUp()
}

type Person interface {
	job()
	growUp()
}

type Student struct {
	age int
}

func (p Student) job() {
	fmt.Println("I am a student.")
	return
}

func (p *Student) growUp() {
	p.age += 1
	return
}

type Programmer struct {
	age int
}

func (p Programmer) job() {
	fmt.Println("I am a programmer.")
	return
}

func (p Programmer) growUp() {
	// 程序员老得太快 ^_^
	p.age += 10
	return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

代码里先定义了 1 个 Person 接口,包含两个函数:

job()
growUp()
1
2

然后,又定义了 2 个结构体,Student 和 Programmer,同时,类型 *Student 、 Programmer 实现了 Person 接口定义的两个函数。注意, *Student 类型实现了接口,Student 类型却没有。 之后,又定义了函数参数是 Person 接口的两个函数:

func whatJob(p Person)
func growUp(p Person)
1
2

在 main 函数里先生成 Student 和 Programmer 的对象,再将它们分别传入到函数 whatJob 和 growUp 函数中,直接调用接口拥有的函数,实际执行的时候是看最终传入的实体类型是什么, 调用的是实体类型实现的函数。于是,不同对象针对同一消息就有多种表现形态,多态就实现了。

更深入一点来说的话,在函数 whatJob () 或者 growUp () 内部,接口 person 绑定了实体类型 *Student 或者 Programmer。根据前面分析的 iface 源码,这里会直接调用 fun 里保存的函数,类似于: s.tab->fun[0] ,而因为 fun 数组里保存的是实体类型实现的函数,所以当函数传入不同的实体类型时,调用的实际上是不同的函数实现,从而实现多态。

运行一下代码,输出如下:

I am a student.
{19}
I am a programmer.
{100}
1
2
3
4
#golang#interface
上次更新: 7/12/2024, 2:37:05 PM
值接收者和指针接收者的区别
接口的动态类型和动态值是什么

← 值接收者和指针接收者的区别 接口的动态类型和动态值是什么→

最近更新
01
为什么我的MySQL会抖一下
07-15
02
HTTP 性能优化面面观
07-12
03
WebSocket:沙盒里的 TCP
07-12
更多文章>
Theme by Vdoing | Copyright © 2022-2024 Ezreal Rao | CC BY-NC-SA 4.0
豫ICP备2023001810号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式