继承与多态的特点

题目:

以下代码能通过编译吗?为什么?

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
package main

import (
"fmt"
)

type People interface {
Speak(string) string
}

type Student struct{}

func (stu *Student) Speak(think string) (talk string) {
if think == "love" {
talk = "You are a good boy"
} else {
talk = "hi"
}
return
}

func main() {
var peo People = Student{}
think := "love"
fmt.Println(peo.Speak(think))
}

答案解析:

​ 在接口类型的变量中持有的是对象的指针而不是对象本身,因此对于实现接口的类型,需要使用指针赋值给接口类型的变量。

1
var peo People = Student{}

​ 将 Student{} 的结构体字面量赋值给 peo,此时会发生编译错误,因为 Student{} 的类型是 Student,而不是 *Student

要使代码通过编译,需要将 Student{} 转换为 *Student 类型的指针,如下所示:

1
var peo People = &Student{}

这样,peo 变量持有的是 *Student 类型的指针,可以调用 peo.Speak() 方法。

以下解析来自 Go语言中文网

​ 继承与多态的特点

在 golang 中对多态的特点体现从语法上并不是很明显。

我们知道发生多态的几个要素:

1、有interface接口,并且有接口定义的方法。

2、有子类去重写interface的接口。

3、有父类指针指向子类的具体对象

那么,满足上述 3 个条件,就可以产生多态效果,就是,父类指针可以调用子类的具体方法。

所以上述代码报错的地方在 var peo People = Student{} 这条语句, Student{} 已经重写了父类 People{} 中的 Speak(string) string 方法,那么只需要用父类指针指向子类对象即可。(Go 中不叫父类,这里是为了好理解)

所以应该改成 var peo People = &Student{} 即可编译通过。(People 为 interface 类型,就是指针类型)


继承与多态的特点
http://example.com/2023/05/29/Go每日一题/继承与多态的特点/
作者
Feng Tao
发布于
2023年5月29日
更新于
2023年5月29日
许可协议