Go 的多态
多态,按字面意思来讲就是多种状态,在面向对象编程语言中,接口的多种不同的实现方式即为多态。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数(Virtual Function) 实现的。
还是用简单的例子来讲明什么要多态吧,我们有一个名为“人”的接口,它有一个方法“我喜欢”,然后一个从火星来的朋友就是程序的使用者,它来到地球之后先问了一个男人:“你喜欢做什么?”,男人调用“我喜欢”这个方法返回给他一个值:“钓鱼”;然后火星人又去问了一个女人同样的问题:“你喜欢做什么?”,然后女人也实现了“人”这个接口,她也调用“我喜欢”这个方法返回给火星人一个值:“购物”……如此这么问下去,发现,每一个人对:“你喜欢做什么?”这个问题的问题都是不一样的,而这种不一样,就是*多态*——从同一种类型的同一个方法中获取完全不同的结果——在这个例子中,接接口就是“人”。
在Go中,我们使用接口来实现多态,如果你看这篇文章时,还不了解Go的接口,建议你先看看我的另一篇文章Go 中的接口,然后再返回来看本文。创建我们创建了一个接口,并且有其它的类型实现了这个接口,那么我们就可以通过这个接口直接访问到每一个类型中所定义的那个方法,而不需要再知道它具体是什么类型,让我们用Go来实现上面那个关于火星人问问题的例子:
package main
import "fmt"
// 定义人这个接口
type Human interface {
// 它有一个方法 iLove
iLove() string
}
// 定义男人
type Man struct {}
// 实现人这个接口
func (man Man) iLove() string {
return "钓鱼"
}
//重复上面的定义
type Woman struct {}
func (woman Woman) iLove() string {
return "购物"
}
func main() {
m := new (Man)
w := new (Woman)
// 一个保存人的数组,它有两人个元素
// 一个为 Man 类型,一个为Woman类型
humans := [...]Human{m,w}
for i, _ := range (humans) {
// 直接调用接口的 iLove 方法
fmt.Println("我喜欢", humans[i].iLove())
}
}输出为:
我喜欢 钓鱼
我喜欢 购物在上面的例子了,我们都是调用了 Human 的 iLove 方法,但是得到了两人个结果,而且我们是直接使用 for 循环来对保存了 Human 数据的数组进行遍历而不是明显地使用 Man.iLove() 方法或者Woman.iLove() 方法。
现在又有一个新问题产生了,这火星人并不知道在地球上我们把人和其它生物是作不同对待的,所以,他还跑去问了一只狗:“你喜欢做什么啊”?狗很客气的“汪!汪汪!汪汪汪!”,那这种新情况出现了我们该怎么办?好办,让我们再来扩展一下上面的例子:
package main
import "fmt"
// 定义生物这个接口
type Organism interface {
// 它有一个方法 iLove
iLove() string
}
// 定义人这种生物
type Human struct {}
// 定义人对生物这个接口的实现
func (human Human) iLove() string {
return "做人该做的事情,我是一只人,不是一个狗!"
}
// 定义男人
type Man struct { Human }
func (man Man) iLove() string {
return "钓鱼,我是一只男人。"
}
//重复上面的定义
type Woman struct { Human }
func (woman Woman) iLove() string {
return "购物,我是一只女人。"
}
// 定义狗
type Dog struct {}
func (dog Dog) iLove() string {
return "汪!汪汪!汪汪汪!我是一个狗!不是一只人。"
}
func main() {
h := new (Human)
m := new (Man)
w := new (Woman)
d := new (Dog)
organisms := [...]Organism{h, m, w, d}
for i, _ := range (organisms) {
// 直接调用接口的 iLove 方法
fmt.Println("我喜欢", organisms[i].iLove())
}
}输出为:
我喜欢 做人该做的事情,我是一只人,不是一个狗!
我喜欢 钓鱼,我是一只男人。
我喜欢 购物,我是一只女人。
我喜欢 汪!汪汪!汪汪汪!我是一个狗!不是一只人。
评论已关闭