为什么OO的继承是一种非常原始的设计

1 view
Skip to first unread message

zhang3

unread,
May 5, 2009, 11:46:17 AM5/5/09
to Zero programming language
在Zero语言中,将语法定义为符号生成规则的集合,在这种框架下,什么变量,类型,操作符,函数,对象,类,消息,接口的区别通通的不存在,全是在既
定规则下被生成的符号。

什么是对象呢?就是当有如下符号串的时候:
Object X{ Y(); }
就可以在“X.”后面跟上Y(...)这一串字符。


那什么是类型呢?就是可以出现在 var X:Y;的Y的位置的那一串字符。

在这个框架下,我们来看看继承是否可以存在,而且是如何存在的。

继承,实际上是一种描述,描述两个符号之间的关系,如果符号A继承符号B,这说明,适合符号B的所有规则对A也适用,而且符号A还可以定义属于自己的规
则出来,这就叫做继承了。从概念上看,纯粹是一种信息描述上的压缩,如果符号A和符号B的规则都很复杂,但是又非常相似,从人的理解上来讲,我们就不需
要单独去了解符号A和符号B的规则了,可以只了解其中一个符号A,还有符号B与A之间的关系就可以了,这实际上是一种概念上的压缩,符合人类的思维方式
和习惯,也符合信息压缩的规律。

于是我们惊奇的发现,一切符号都是可以继承的。变量,类型,操作符,函数,对象,类,消息,接口,无一不是,而继承,本身也是一种符号,遵循一定的普遍
规则。
让我们来看一看,把继承扩展到如此之大的范围到底有何作用?
一个例子是,我们可以用于操作符重载,从+操作符继承出另一个同名操作符出来,并赋予不同的规则。
第二个例子是,可以从某个类型继承出某种子类型。例如,从整型继承出一个从1到365的子类型,遵循一切整数类型的符号规则,同时又增加了区间限制。
第三个例子是,函数的继承,有很多函数,我们根本不用把它们强行装入到一个类中使用,直接用就可以了,但是它们也存在继承的需要。
其他更有趣的概念是,类的继承,和对象的继承是不一样的,其中微妙,目前恐怕没法一一道来。在这里,类不再是一个概念上的抽象,而是一个被描述出来的代
码实体,其实是可以当作对象的原型,也是对象的一种。

接下来,更深入的分析一下,这个继承,到底还有什么样的特性:
1 继承不再是一种单纯的符号,而是附带了大量信息。以我们熟悉的ClassA和ClassB为例,假设把继承当作一个函数f,那么ClassB继承
ClassA可以表示为: ClassB=f(ClassA)
这说明,ClassA的表达,经过f的运算,得到ClassB,而对于不同的Class,f运算的具体内容是不同的,有的是增加成员,有的是重载成员,
这取决于两个Class之间的相同和相异的部分。

运算函数f(暂时叫做函数,实际上是一种符号规则的运算)本身,就是继承的具体含义。而这种运算,可以增加成员,这样ClassA就是ClassB的父
类,也可以减少成员,这样ClassA就是ClassB的子类,还可以在增加某个成员的同时,减少另外一个成员,那么,父子关系是怎样的呢?其实,这种
继承不存在强行规定的父子关系,不能归类为父子关系的,可以叫做相似关系,这与我前面一篇文章:单调的继承-系列之四中提出的观点一致:我们实际上处理
的类的概念更多的是家族相似,而并非严格的Is-A关系。至于这种关系的含义具体是什么,f函数中已经有严格精确的定义。

更进一步,我们来看看,如何通过求对函数f求值的方法(将f当作变量求值)来进行重构:

假设我们已经写出ClassA和ClassB,各自有一堆代码:
ClassA{... ...} ; ClassB{... ...} ;
然后我们发现它们是如此的相似,于是认为需要在这两个概念之间建立继承关系,于是有:ClassB=f(ClassA)。
这个符号方程式,其实我们完全可以看作代数中的方程式, ClassA,ClassB是已知的,而f未知。于是可以求得f,这里所求得的f,就是
ClassA和ClassB之间的继承关系。当然也可以列出 ClassA=g(ClassB)来求解,效果是一样的,只不过求出来的g函数跟f函数是
互为反函数的关系。在经过求值之后,我们可以在程序中添加上这么一句话,程序于是变成了:
ClassA{... ...} ; ClassB{... ...} ;ClassB=f(ClassA);f={... ...};
这里可以看出,由于ClassA和ClassB都很复杂,所以前面两行代码信息量都很大,第三行信息量很小,又因为两个Class很相似,所以第四行的
信息量也很小。上面的四行,信息实际是冗余的,对ClassB是重复描述,于是我们删去第二行,得到:
ClassA{... ...} ;ClassB=f(ClassA);f={... ...};
这样,我们就完成了抽象和重构的任务,从这个过程中,我们可以看出,继承的最直接的功能,就是减小了信息量,方便了记忆和理解。

最后看一个小魔术,既然f也是一个符号,那么它能否被继承呢?是,完全可以。例如在上面最后重构结束之后,我们得到了f,要定义一个f1继承这个f,然
后用这个f1作用于ClassA,结果是得到了ClassC=f1(ClassA),这同样有意义,这实际上是说,ClassB与ClassA存在差
异 f,ClassC和ClassA之间存在差异f1,差异f1和差异f区别不大。

从这里可以看出,OO的继承,实际上是非常原始的,常见的流行语言中的继承,就更加形而下,几乎沦落为只是略有甜味的语法糖。唯有把一切当作符号,才可
以让人脑中的继承概念在语言中发挥出应有的威力。

Reply all
Reply to author
Forward
0 new messages