面向对象语言概论(四)

原创 2002年11月02日 00:25:00

 

四,彻底划清界限(继续分离SubclassingSubtyping

在第二节我们讨论了部分分离Subclassingsubtyping的方法,即subclassing-implies-subtyping. 现今的许多面向对象语言,如Java, C#都是采用了这种技术。除此之外,还有一种进一步分离Subclassingsubtyping的方法。这种被称作inheritance-is-not-subtyping的方法通过完全割裂subclassingsubtyping之间的联系而在更大程度上方便了代码的重用。

它的产生很大程度上是由于人们想要使用在反协变位置上的Self类型 (如Self类型的参数)。当然,增大继承的能力的代价是subsumption的灵活性降低了。当Self类型出现在反协变的位置上时,subclass不再意味着subtype, 因此,subsumption也就不存在了。

 

下面请考虑这样两个类型:

ObjectType Max is

            var n: Integer;

            method max(other:Max): Max;

end;

ObjectType MinMax is

            var n: Integer;

            method max(other:MinMax): MinMax;

            method min(other:MinMax): MinMax;

end;

再考虑两个类:

class MaxClass is

            var n:Integer :=0;

            method max(other: Self): Self is

                        if self.n > other.n then return self else return other end;

            end;

end;

subclass MinMaxClass of MaxClass is

            method min(other: Self): Self is

                        if self.n < other.n then return self else return other end;

            end;

end;

 

方法minmax是二元的,因为它操作两个对象:selfother. other的类型是一个出现在反协变位置上的Self类型。

注意,方法max有一个反协变的参数类型Self, 并且它被从类MaxClass继承到了MinMaxClass.

 

很直观地,类MaxClass对应着类型Max;类MinMaxClass对应着类型MinMax. 为了精确地表示这种对应关系,我们必须针对包含使用Self类型的成员的类重新定义ObjectTypeOf,以便得到ObjectTypeOf(MaxClass) = Max, ObjectTypeOf(MinMaxClass) = MinMax

 

为了使以上的等式成立,我们把类中的Self类型映射到ObjectType中的类型名称本身。我们同时让Self类型在继承的时候特化。

在本例中,当我们映射MinMaxClass的类型时,我们把继承来的max方法中的Self类型映射到MinMax类型。而对MaxClassmax方法的Self类型,我们使用Max类型。

如此,我们可以得到,任何MaxClass生成的对象,都具备Max类型。而任何MinMaxClass生成的对象都具备MinMax类型。

 

虽然MinMaxClassMaxClass的子类,但这里MinMax却不是Max的子类型(subtype).

举个例子,如果我们假设subtype在这种情况下成立,那么,对以下的这个类:

 

subclass MinMaxClass’ of MinMaxClass is

            override max(other: Self): Self is

                        if other.min(self) = other then return self else return other end;

            end;

end;

 

根据我们对Self类型的映射规则和基于结构的subtype规则,我们知道,ObjectTypeOf(MinMaxClass’) = MinMax, 所以,对任何MinMaxClass’生成的对象mm’ ,我们可以知道mm’ : MinMax.

而如果MinMax <: Max成立,根据subsumption, 我们就能推出mm’ : Max.

于是当我们调用mm’.max(m)的时候,m可以是任何Max类型的对象。但是,当max的方法体调用other.min(self)的时候,如果这个other不具有min方法,这个方法就会失败。

由此可见,MinMax <: Max并不成立。

子类(subclass) 在使用反协变的Self类型时就不再具有subtype的性质了。

 

 

五,对象协议 Object Protocol

 

 

从上一节的讨论,我们看到对使用反协变Self类型的类,subclass不再是subtype了。这是一个令人失望的结果,毕竟很多激动人心的面向对象的优点是通过subtype, subsumption来实现的。

不过,幸运的是,虽然失去了subtype, 我们还是可以从中挖掘出来一些可以作为补偿的有用的东西的。只不过,不象subtype, 我们不能享受subsumption了。

下面就让我们来研究这种新的关系。

 

在第四节的MinMax的例子中,subtype不再成立;简单地使用泛型,引入

ObjectOperator P[M <: Max] isend; 也似乎没有什么用。P[Max]虽然成立,但P[MinMax]却是不合法的,因为MinMax <: Max不成立。

 

但是,直观上看,任何支持MinMax这种协议的对象,也支持Max协议的 (虽然我们还不知道这个“协议”到底是个什么东西)。于是,似乎隐隐约约地又一个叫做“子协议”(subprotocol)的家伙在向我们招手了。

为了发现这个子协议的关系,让我们先定义两个type operator (还记得吗?就是作用在类型上的函数)

ObjectOperator MaxProtocol[X] is

            var n: Integer;

            method max(other: X) :X;

end;

ObjectOperator MinMaxProtocol[X] is

            var n:Integer;

            method max(other: X):X;

            method min(other: X):X;

end;

 

这样,Max = MaxProtocol[Max], MinMax = MinMaxProtocol[MinMax]

更一般地说,我们可以定义:

什么 = 什么-Protocol[什么]

 

还记得lamda-calculus里的fixpoint吗?给定一个函数F, F(fixpoint(F)) = fixpoint(F)

而在我们这个子协议的type operator里,如果我们认为type operator是作用于类型的函数的话, 那么这个“什么”,就是“什么-Protocol”函数的fixpoint啊!

也就是说:

什么= fixpoint (什么-Protocol).

 

除了以上的fixpoint的性质,我们还发现了存在于MaxMinMax之间的关系。

首先,MinMaxMaxProtocol的一个post-fixpoint,即:

MinMax <: MaxProtocol[MinMax]

其次,我们可以看出:

MinMaxProtocol[Max] <: MaxProtocol[Max]

MinMaxProtocol[MinMax] <: MaxProtocol[MinMax]

 

最后,如果我们用<::来表示一个更高阶的子类型关系:

P <:: P’ 当且仅当 P[T] <: P’[T] 

那么,MinMaxProtocol <:: MaxProtocol.

 

 

对于子协议的定义,我们可以采取上面的<::的定义,即:

如果S-Protocol<::T-Protocol, 那么我们称类型S和类型T之间是子协议关系。 (1)

 

我们也可以不用这个高阶的关系,仍然使用<:这个subtype的关系:

如果S<:T-Protocol[S], 那么我们称类型S和类型T之间是子协议关系。 (2)

 

其实,第一个定义似乎更直观一点,它更明确地显示出子协议关系是作用于类型上的函数(type operator)之间的关系,而不是类型之间的关系。

 

使用泛型技术,如果我们的某一个类型需要一个实现MaxProtocol的类型来实例化的话,我们可以采用下面两种方法中的一种:

ObjectOperator P1[X <: MaxProtocol[X]] is … end; (1)

ObjectOperator P2[P <:: MaxProtocol] is … end; (2)

 

这两种方法在表达能力上是相同的。第一种方法叫做F-bounded parameterization. (译者按,Generic Java据说就采用了这个方法);第二种方法叫做 higher-order bounded parameterization.

 

对于具体语言的实现,为了方便,我们可以隐藏这个type operator. 语法上可以直接对类型支持subprotocol的关系(用<#来表示)。

对我们的MinMax的例子来说,我们就有:

MinMax <# Max.

(译者按,绕了一大圈,什么fixpoint啊,post-fixpoint啊,什么高阶关系啦,希望没把你绕晕。其实,你只需要记住MinMax <# Max, 就八九不离十了,呵呵)

 

<#这个关系并不具有subsumption的性质,所以,你不能指望从它身上得到传统OO里面的多态。但是,与泛型相结合,它却是非常有用的。

比如说,我们可以对我们的所有你用来当作参数传给我的基于GP的快速排序模板函数给出这样的约束:用来实例化这个模板函数的的类型必须支持Comparable协议。

 

(译者按,使用它对加强C++中的模板的类型安全会很有用。其实,对使用gp的程序来说,也许子协议约束比子类型约束更合理。子类型的sumbsumption要求多态,即dynamic dispatch。但很多时候,我们并不一定需要类型参数支持多态。请参看我的拙文:http://www.allaboutprogram.com/bb/viewtopic.php?t=255

 

 

 

 

思考题:

1. Java是支持CovariantArray的。你可以把一个String[] 类型的对象当作一个Object[]类型来使用。

那么,Javacovariant array是类型安全的吗?为什么?

2. 大家都知道经典的矩形和正方形之间的类型关系吧?在支持get, set的正方形和矩形之间,并不存在subtype的关系,这是因为subsumptiongetset操作是不安全的。但是,是否正方形和矩形之间就不可能有subtype的关系呢?如果矩形的类型只支持get, 结果会是什么?如果正方形只支持set, 结果又是什么呢?

 

下章预告:

基于对象的面向对象语言。

数据库系统概论学习笔记(四):SQL的简单应用之数据查询

嗯……最实用的部分,其他都可以不会,唯独这个必须熟练吧 —— 数据查询...
  • credolhcw
  • credolhcw
  • 2017年02月22日 14:27
  • 313

蓝桥杯省赛题 四平方和

四平方和四平方和定理,又称为拉格朗日定理: 每个正整数都可以表示为至多4个正整数的平方和。 如果把0包括进去,就正好可以表示为4个数的平方和。比如: 5 = 0^2 + 0^2 + 1^2 + ...
  • iamxiongwei163
  • iamxiongwei163
  • 2017年02月25日 14:51
  • 275

软件工程概论常用问答

说实话,这是为了考试准备的。明天是是软件设计与体系结构的考试。。 虽然搞ACM,但是自己的专业本行还是不能丢掉啊。。况且自己的ACM实在是渣。 这个六月份把所有的考试都努力刷个高分,GPA刷上去,为未...
  • u012848631
  • u012848631
  • 2015年06月08日 15:29
  • 730

《数据库系统概论》复习笔记

期末复习顺便总结下,书本为高等教育出版社的《数据库系统概论》。
  • hcbbt
  • hcbbt
  • 2014年01月12日 01:03
  • 13692

数据库系统概论第五版学习笔记数据库完整性 第五章

一、基本内容 1. 定义:数据的正确性和相容性 2. 内容涉及    1)提供定义完整性约束条件的规则   ‚2)提供完整性检查的方法    3)进行违约处理 3. 分类 实体完整性...
  • M_Eve
  • M_Eve
  • 2016年12月04日 16:46
  • 722

数据库系统概论期末考试卷【详解】

声明:以下内容有些概念会模糊,有些概念可能会错误!希望指正!也希望读者能带着严谨的态度看【害怕】数据库系统概述()数据库的4个基本概念()1.数据 2.数据库 3.数据库管理系统 4.数据库系统...
  • KEYboarderQQ
  • KEYboarderQQ
  • 2017年05月31日 13:53
  • 1903

第七届蓝桥杯省赛Java语言C组_四平方和

题目: 四平方和 四平方和定理,又称为拉格朗日定理: 每个正整数都可以表示为至多4个正整数的平方和。 如果把0包括进去,就正好可以表示为4个数的平方和。 比如: 5 = 0^2 + 0^2 + 1...
  • qq_36128330
  • qq_36128330
  • 2017年02月25日 22:58
  • 369

数据库基本概念-《数据库系统概论 王珊》读书笔记1

1. 数据,数据库,数据库管理系统,数据库系统 数据 Data 数据库中存储的基本对象 数据库 DB 长期存储在计算机内,有组织的,可共享的大量数据的集合 数据库管理系统 DBMS 介...
  • u013721259
  • u013721259
  • 2014年12月04日 17:22
  • 806

数据库系统概论总结

数据库复习文档一、数据模型 信息世界中:实体,属性,域,码(键),实体型,实体集,联系 机器世界中:字段(对应属性),记录,文件 数据模型有两种 ,概念数据模型(概念模型/信息模型),基本数据模...
  • qq_32623363
  • qq_32623363
  • 2017年06月12日 23:55
  • 599

【2017上半年自考总结】——书要看三遍之《操作系统概论》

前言    这次自考,小编报考了《操作系统概论》和《运筹学》。这次自考给小编的感触是学习一定要走心,一定要书看三遍,一定要讲究方法。  《操作系统概论》     在学习操作系统之前,一定要先了解计...
  • u013044029
  • u013044029
  • 2017年04月16日 22:02
  • 688
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:面向对象语言概论(四)
举报原因:
原因补充:

(最多只允许输入30个字)