4. Subsumption和Dynamic Dispatch (译者按:呵呵,黔驴技穷,找不到合适的翻译了)
从上述的几个例子来看,似乎子类只是用来从父类借用一些定义,以避免重复。但是,当我们考虑到subsumption, 事情就有些不同了。什么是Subsumption呢?请看下面这个例子:
var myCell: InstanceTypeOf(cell) := new cell;
var myReCell: InstanceTypeOf(reCell) := new reCell;
procedure f(x: InstanceTypeOf(cell)) is … end;
再看下面这段代码:
myCell := myReCell;
f(myReCell);
在这两行代码中,头一行把一个InstanceTypeOf(reCell)类型的变量赋值给一个InstanceTypeOf(cell)的变量。而第二行则用InstanceTypeOf(reCell)类型的变量作为参数传递给一个参数类型为InstanceTypeOf(cell)的函数。
这种用法在类似Pascal的语言中是不合法的。而在面向对象的语言中,依据以下的规则,它则是完全正确的用法。该规则通常被叫做subtype polimorphism, 即子类型多态(译者按:其实subtyping应该是OO语言最区别于其它语言的地方了)
如果c’是c的子类,并且o’是c’的一个实例,那么o’也是c的一个实例。
更严格地说:
如果c’是c的子类,并且o’: InstanceTypeOf(c’),那么o’: InstanceTypeOf( c ).
仔细分析上面这条规则,我们可以在InstanceTypeOf的类型之间引入一个满足自反和传递性的子类型关系, 我们用<:符号来表示。(译者按:自反就是说, 对任何a, a 关系 a都成立,比如说,数学里的相等关系就是自反的。而传递性是说,如果a 关系 b, b 关系c, 就能推出a 关系c。 大于,小于等关系都是具备传递性的)
那么上面这条规则可以被拆成两条规则:
1. 对任何a: A, 如果 A <: B, 那么 a: B.
2. InstanceTypeOf(c’) <: InstanceTypeOf(c) 当且仅当 c’是c的子类
第一条规则被叫做Subsumption. 它是判断子类型(注意,是subtype, 不是subclass)的唯一标准。
第二条规则可以叫做subclassing-is-subtyping (子类就是子类型,绕嘴吧?)
一般来说,继承都是和subclassing相关的,所以这条规则也可以叫做:inheritance-is-subtyping (继承就是子类型)
所有的面向对象语言都支持subsumption (可以说,没有subsumption, 就不成为面向对象)。
大部分的基于类的面向对象语言也并不区分subclassing和subtyping. 但是,一些最新的面向对象语言则采取了把subtyping和subclassing分开的方法。也就是说,A是B的子类,但A类的对象却不可以当作B类的对象来使用。(译者按:有点象C++里的私有继承,但内容比它丰富)