多态(polymorphism)
多态是接口的一个关键功能和Go语言的一个重要特性。
当非接口类型T
的一个值t
被包裹在接口类型I
的一个接口值i
中,通过i
调用接口类型I
指定的一个方法时,事实上为非接口类型T
声明的对应方法将通过非接口值t
被调用。 换句话说,调用一个接口值的方法实际上将调用此接口值的动态值的对应方法。 比如,当方法i.m
被调用时,其实被调用的是方法t.m
。 一个接口值可以通过包裹不同动态类型的动态值来表现出各种不同的行为,这称为多态。
当方法i.m
被调用时,i
存储的实现关系信息的方法表中的方法t.m
将被找到并被调用。 此方法表是一个切片,所以此寻找过程只不过是一个切片元素访问操作,不会消耗很多时间。
注意,在nil接口值上调用方法将产生一个恐慌,因为没有具体的方法可被调用。
一个例子:
1 | package main |
输出结果:
1 | 过滤之前: |
在上面这个例子中,多态使得我们不必为每个过滤器类型写一个单独的filteAndPrint
函数。
除了上述这个好处,多态也使得一个代码包的开发者可以在此代码包中声明一个接口类型并声明一个拥有此接口类型参数的函数(或者方法),从而此代码包的一个用户可以在用户包中声明一个实现了此接口类型的用户类型,并且将此用户类型的值做为实参传递给此代码包中声明的函数(或者方法)的调用。 此代码包的开发者并不用关心一个用户类型具体是如何声明的,只要此用户类型满足此代码包中声明的接口类型规定的行为即可。
事实上,多态对于一个语言来说并非一个不可或缺的特性。我们可以通过其它途径来实现多态的作用。 但是,多态可以使得我们的代码更加简洁和优雅。