继承多态性
- 来源: https://www.freebasic.net/wiki/wikka.php?wakka=ProPgPolymorphism
- 最后更新: 2022-11-29
继承多态性是从基类型调用派生类型成员过程而无需关心所处理对象的真实类型的能力。
前言:
继承多态性(子类型多态性)是为可以具有不同类型的实体提供单一接口的概念。
更准确地说,同一接口由每个属于同一继承层次结构的类型中具有相同标识符的成员过程实现。
借助"抽象/虚拟"过程,可以仅使用基类型编写代码,该代码将自动调用派生类型的过程。
这样就可以调用对象的过程而无需关心其固有类型。
通过对几种不同类型使用相同的过程名称,多态性允许更加通用的编程(抽象)。
编码者在调用基类型过程时不必知道过程将应用于其上的对象的精确类型。只需知道该类型将实现该过程即可。
例如,一个过程 moving() 将根据调用时所引用实例的真实派生类型执行适当的移动。这允许程序调用 instance.moving() 而无需担心 instance 的真实派生类型。
继承多态性的运作
在继承自基类型的派生类型中重新定义过程的能力称为特化。
这样就可以调用对象的过程而无需关心其固有类型:这就是继承多态性。
这使得可以通过基类型这个公共接口来屏蔽对象族的特化类型的细节,从而抽象这些细节。
使用基类型的指针或引用来指定对象
考虑一组对象,其实例化类型是基类型的派生类型,那么所有这些对象都可以通过将它们视为基类型的对象来以统一的方式操作。
更好的是,某些行为可以根据每个对象的实例化类型进行特化。换句话说,即使这些对象的行为保持特定,使用同一继承层次结构中的不同对象也是同质的。
因此,指向派生类型实例的基类型指针或引用可用于操作此类对象。
在基类型中覆盖抽象/虚拟过程,在派生类型中提供特化过程
要在类型中声明抽象/虚拟过程,该类型必须(直接或间接)Extends(扩展)内置 Object 类型。
派生类型可以通过声明具有相同标识符和签名(即相同的参数数量和类型、相同的调用约定,以及如有返回类型,则相同的返回类型(或对于按引用或按指针返回,可以是派生类型的返回))的过程来覆盖其基类型中声明的抽象/虚拟过程:
通常,基类型的引用/指针只能访问同一类型或层次结构上层类型中的过程(编译时静态绑定),即使该引用/指针引用的是基类型派生的实例化类型的对象。
但当基类型过程是抽象/虚拟的时,这告诉运行中的程序解析与真实对象类型最相关的覆盖过程(运行时动态绑定)。
限制:
多态性与以下情况不直接兼容:
任何
New[]或Delete[]运算符(语句/表达式/重载运算符的数组版本),因为使用子类型指针(而非真实类型)无法访问其他元素(第一个元素除外),甚至重载运算符
Delete也不直接兼容,因为它不能声明为 virtual(因为是静态的)。
与其在派生类型指针上调用此类运算符 Delete([]) 语句,更安全的方法是(在基类型指针上)调用一个覆盖的用户虚拟成员过程,该过程将在派生类型级别自动启动运算符 Delete([]) 语句。
通过示例学习继承多态性:'图形类型集合'
在下面提出的示例中,多态部分被分解,以便更好地展现多态机制所必需的所有元素。
所选的通用基类型是由两个图形点和一种颜色定义的任何"图形形状"(抽象)。
专门的派生类型是"图形直线"、"图形矩形"和"图形圆形"(均由两个图形点和一种颜色定义):
"图形直线"连接点1和点2。
"图形矩形"以点1(顶部左侧)和点2(底部右侧)为对角顶点。
"图形圆形"以点1为圆心,过点2。
在通用基类型中声明的抽象过程,必须在每个专门的派生类型中定义,是在图形窗口中绘制特化形状的图形绘制过程。
两个图形点和颜色是通用数据,因此在通用基类型中通过组合引入了三个通用数据字段。
还定义了一个"图形点"类型,封装了 x/y 坐标值(声明为私有),以便通过属性(但这些属性是公共的)来控制其有效性(取决于定义的图形屏幕大小)。
命名约定:
通用基类型名称:
GraphicForm2P专门派生类型名称:
GraphicLine2P、GraphicBox2P、GraphicCircle2P虚拟过程名称:
drawGraphicForm2P()附加类型名称(通过组合包含在通用类型中):
GraphicPointGraphicPoint类型声明(用于组合到通用基类型中的附加类型):GraphicForm2P类型声明(通用基类型):GraphicLine2P、GraphicBox2P、GraphicCircle2P类型声明(专门的派生类型):示例完整代码:
参见
Type (UDT),Extends,Object,Operator Is (rtti)Virtual,Abstract,OverridePointer,Reference- 组合、聚合、继承
- OBJECT 内置类型与 RTTI 信息
- 使用隐式/重载 New([]) 和 Delete([]) 运算符与继承多态性
返回 目录