大多数面向对象的程序设计系统,都是通过继承来提供多态的。也就是说,设想的 Flea 和 Tyrannosaur 类可能都是从某个 Animal 类继承来的。每个类都将重写 Animal 类的 Bite 方法,以提供自己的噬咬特点。
多态来自于这个事实:可以调用属于某类对象的 Bite 方法—该类可以是从 Animal 中派生出来的任意类,而不必知道该对象到底属于哪一个类。
Visual Basic 不用继承来提供多态。Visual Basic 是通过多重 ActiveX 接口来提供多态的。在构成 ActiveX 规格说明基础的部件设计模型 (COM) 中,多重接口允许软件部件系统在不扩散现有代码的情况下进行展开。
一个接口是一组相关的属性和方法。ActiveX 规格说明的许多内容是关于实现一些标准接口的,这些标准接口是用来获得系统服务或者为其它程序提供功能。
在 Visual Basic 中,可以创建一个 Animal 接口,并用自己的 Flea 和 Tyrannosaur 类予以实现。然后就可以调用任何一种对象的 Bite 方法,而无须知道它到底是哪一种对象。
从性能方面考虑,多态是很重要的。为了认识这一点,考虑下面的函数:
Public Sub GetFood(ByVal Critter As Object, _ ByVal Food As Object) Dim dblDistance As Double '
计算到食物所在处距离的代码(略)。Critter.Move dblDistance '
后期绑定Critter.Bite Food '
后期绑定End Sub
对 Critter
来说,Move 方法和 Bite 方法是后期绑定的。后期绑定在 Visual Basic 编译时不能决定变量包含何种对象时发生。在本示例中,Critter 参数被声明为 As Object,因此在运行时,它可能包含对任何类型对象引用,如 Car 或者 Rock。
因为它不可能指明对象将是什么,所以 Visual Basic 编译一些附加的代码,用这些代码来询问该对象是否支持已经调用的方法。如果该对象支持这种方法的话,那么附加的代码将调用它;反之,附加的代码将会产生一个错误。每种方法或者属性的调用都会引入这个额外开销。
相比较而言,接口则允许前期绑定。当 Visual Basic 在编译时明确知道正在调用什么样的接口时,它将检查一下类型库,看看那个接口是否支持该方法。然后 Visual Basic 就可以用一张虚拟函数表 (vtable),按直接跳转到该方法进行编译。这样做比起后期绑定来要快许多倍。
现在,假设 Move 和 Bite 方法属于 Animal 接口,而且动物的所有类都提供该接口。Critter 参数现在就可以被声明为 Animal 了,而且 Move 和 Bite 方法也将是前期绑定的:
Public Sub GetFood(ByVal Critter As Animal, _ ByVal Food As Object) Dim dblDistance As Double '
计算到食物所在处距离的代码(略)。Critter.Move dblDistance '
前期绑定(vtable)
。Critter.Bite Food '
前期绑定(vtable)
。End Sub
详细信息 在下面“创建和实现接口”这一节中,创建了一个 Animal 接口,并在 Flea 和 Tyrannosaur 类中实现它。