版权归原作者所有,如有侵权,请联系我们

[科普中国]-多分派

科学百科
原创
科学百科为用户提供权威科普内容,打造知识科普阵地
收藏

软件工程师通常把代码写进代码块中,代码块通常称作过程,函数,方法。代码通过被调用来执行,调用时将控制权传入函数中,当函数执行完成后将控制权返回给调用者。多分派(Multiple dispatch or multimethods)是某些面向对象编程语言的特性,函数或者方法的分派取决于运行时参数的对象类型。它是对方法调用只能由调用者决定的单分派的扩展。多分派概括了两个或多个对象的动态分派。

简介一个方法所属的对象叫做方法的接收者,方法的接收者与方法的参量统称为方法的宗量。根据分派可以基于多少种宗 量,可以将面向对象的语言分为单分派语言和多分派语言。单分派语言根据一个宗量的类型进行对方法的选择,多分派语言根据多于一个宗量的类型对方法进行选择。Java是单分派语言,因为它动态分派仅仅会考虑到方法的接收者类型,同时又是静态的多分派语言,因为它对重载方法的分派会考虑到方法的接收者类型以及方法的所有参量的类型。 在一个支持动态单分派的语言里(如Java),有两个条件决定了一个请求会调用哪一个操作,一是请求的名字,二是接 收者的真实类型,单分派限制了方法的选择过程,使得只有一个宗量可以被考虑到,这个宗量通常就是方法的接收者1。

简单来说,单分派是指调用一个对象的方法仅由对象的类型决定。多分派是指调用一个对象的方法不仅由对象的类型决定,同时还由其他因素决定,比如方法参数的类型等等。

分派变量被声明时的类型叫做变量的静态类型,或叫做明显类型,而变量所引用的对象的真实类型叫做实际类型,这种根据对象的类型而对方法进行的选择,就是分派。分派是面向对象的语言所提供的关键特性之一。根据对象的类型而对方法进行的选择,就是分派(Dispatch)。根据分派发生的时期,可以将分派分为两种,即分派分静态分派和动态分派。

静态分派(Static Dispatch) 发生在编译时期,分派根据静态类型信息发生。方法重载(Overload)就是静态分派。即所谓的编译时多态。

动态分派(Dynamic Dispatch) 发生在运行时期,动态分派动态地置换掉某个方法。面向对象的语言利用动态分派来实现方法置换产生的多态性。即所谓的运行时多态。在有些编程语言中,这种数据类型的区分可以被延后到运行时,例如后绑定(late binding)。分派发生在运行时并依据运行时方法的参数类型,这种方式的分派通常也被称为多方法(multimethods)。

多态在编程语言和类型论中,多态(polymorphism)指为不同数据类型的实体提供统一的接口。多态类型(polymorphic type)可以将自身所支持的操作套用到其它类型的值上。

计算机程序运行时,相同的消息可能会送给多个不同的类别之对象,而系统可依据对象所属类别,引发对应类别的方法,而有不同的行为。简单来说,所谓多态意指相同的消息给予不同的对象会引发不同的动作。

多态也可定义为“一种将不同的特殊行为和单个泛化记号相关联的能力”。

多态可分为变量多态与函数多态。变量多态是指:基类型的变量(对于C++是引用或指针)可以被赋值基类型对象,也可以被赋值派生类型的对象。函数多态是指,相同的函数调用界面(函数名与实参表),传送给一个对象变量,可以有不同的行为,这视该对象变量所指向的对象类型而定。因此,变量多态是函数多态的基础。多态还可分为:

动态多态(dynamic polymorphism):通过类继承机制和虚函数机制生效于运行期。可以优雅地处理异质对象集合,只要其共同的基类定义了虚函数的接口。也被称为子类型多态(Subtype polymorphism)或包含多态(inclusion polymorphism)。在面向对象程序设计中,这被直接称为多态。

静态多态(static polymorphism):模板也允许将不同的特殊行为和单个泛化记号相关联,由于这种关联处理于编译期而非运行期,因此被称为“静态”。可以用来实现类型安全、运行高效的同质对象集合操作。C++ STL不采用动态多态来实现就是个例子。

参数化多态(Parametric polymorphism):把类型作为参数的多态。在面向对象程序设计中,这被称作泛型编程。

对于C++语言,带变量的宏和函数重载(function overload)机制也允许将不同的特殊行为和单个泛化记号相关联。然而,习惯上并不将这种函数多态(function polymorphism)、宏多态(macro polymorphism)展现出来的行为称为多态(或静态多态),否则就连C语言也具有宏多态了。谈及多态时,默认就是指动态多态,而静态多态则是指基于模板的多态。

有关术语参数多态在程序设计语言与类型论中是指声明与定义函数、复合类型、变量时不指定其具体的类型,而把这部分类型作为参数使用,使得该定义对各种具体类型都适用2。参数化多态使得语言更具表达力,同时保持了完全的静态类型安全。这被称为泛型函数、泛型数据类型、泛型变量,形成了泛型编程的基础。

参数多态名字来源于其发明人克里斯托弗·斯特雷奇,与特设多态(ad hoc polymorphism)相对。特设多态是指一个多态函数有多个不同的实现,依赖于其实参而调用相应版本的函数。因此,特设多态仅支持有限数量的不同类型。

特定多态(ad hoc polymorphism)是程序设计语言的一种多态,多态函数有多个不同的实现,依赖于其实参而调用相应版本的函数。因此,特设多态仅支持有限数量的不同类型。函数重载乃至运算符重载也是特设多态的一种。

特定多态的名字来源于其发明人克里斯托弗·斯特雷奇于1967年8月在哥本哈根的计算机程序设计暑期学校发表了著名论文Fundamental Concepts in Programming Languages中首次提出了参数多态、特设多态、左值、右值等概念。特设多态与参数多态相对。ad hoc在这里并不是贬义,而是指这类多态并不是类型系统的基本特性,不是像参数多态那样适用于无穷多的类型,而是针对特定问题的解决方案。

换言之,参数多态对各模板参数的实现,是根据模板的通用(generically)的行为的抽象,即泛型的语义;而特设多态可以针对不同的版本实现完全不同的行为,或曰对于每个不同的模版参数都有单独的版本来应对。打个比方:假如我们要把原材料切成两半—

参数多态:只要能“切”,就用工具来切割它;

特设多态:根据原材料是铁还是木头还是什么来选择不同的工具来切。

本词条内容贡献者为:

王沛 - 副教授、副研究员 - 中国科学院工程热物理研究所