多态性机制

方法调用分为解析调用和分派调用两大类。

解析调用

解析调用是一个静态过程,在编译期间进行。

静态解析的方法需要满足条件“编译器可知,运行时不可变”,此类方法也被称为非虚方法,包括静态方法(直接与类型关联),私有方法(外部不可访问),实例构造器和父类方法。final方法也是一种非虚方法。

分派调用

分派调用有静态分派和动态分派(好像动态绑定这个名字用的更多)。

静态分派:根据静态类型定位方法执行版本的分派行为,静态分派发生在编译期间。典型应用:方法重载。

动态分派:根据实际类型定位方法执行版本的分派行为,动态分派发生在运行期间。典型应用:方法重写。


示例(Kotlin代码)


类声明
识别者类
主函数

运行结果:

I am a man.

I am a woman.

Human.

Human.

其中,a,b的静态类型都是Human。可以看出,方法重载依据静态类型进行分派,方法重写依据动态类型进行分派。


分派还分为单分派和多分派,主要是看分派行为所依据的条件个数,比如动态分派,只依据实际类型进行分派,就是单分派。但是感觉这个东西用处不大。。


动态绑定的实现

C++的多态主要是通过虚表和虚指针实现的。Java也类似,主要是通过方法表来实现的。

父类和子类的方法表偏移量是一致的,这是一个关键。

在动态绑定的过程中,首先会得到父类的方法表中该方法的偏移量,然后根据this指针得到该对象的动态类型(实际类型),根据偏移量找到该类型方法表中对应的方法,如果有重写父类的该方法,则直接调用,如果没有,则按照继承关系向上查找。

而在接口继承中,由于类可以继承多接口,因此偏移量可能会不同,这时,每次方法调用都要搜索方法表。因此,接口调用的效率比类调用要低一些。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容