继承是什么和应该是什么
fixopen() 09:32:22
继承,类不变性之间的关系是不是很亲密?
继承仅仅表达为增加特有的属性是不是不够完善?是不是还要有对已有的属性进行限制的能力才完善?类不变性可以非常自然的为heir增加parent原有属性的限制。
考虑多边形与矩形的继承关系。矩形就是边数为4,相邻边正交的多边形。可惜的是,如果没有对多边形原有属性的限制,很难表达这种继承关系,也导致了很少有人这样使用继承,非常自然和直观的继承。
狐狸发 () 09:37:22
有的时候最好不要用继承来描述普遍-特例这样的关系
一棵大白菜() 09:38:12
why?这是抽象性的表达方法
狐狸发 () 09:38:15
一般这种情况都是人为的经验性的行为,并不符合事物演化的规律
fixopen() 09:38:18
为什么?继承不就是用来描述这样的关系的么?
狐狸发 () 09:39:07
你说三角形和等边三角形有什么继承的关系么,还是人为的这样认为?
fixopen() 09:39:05
是因为现有语言大多数都不支持类不变性导致我们不能这样自然的描述吧。
fixopen() 09:39:28
等边三角形自然是三角形的heir。你不觉得?
一棵大白菜() 09:39:32
比如:大家来吃饭啦-〉fixopen,狐狸,无限....来吃饭啦
狐狸发 () 09:40:35
等边三角形只是3条都相等,只是属性上有区别,他就是三角形
一棵大白菜() 09:40:52
三角形具有等边三角形等其它特异三角形的通性
fixopen() 09:41:03
是啊,所以等边三角形继承自三角形非常自然和直观啊。
狐狸发 () 09:41:27
这时候不应该用继承来描述
fixopen() 09:41:28
可惜的是,我们的大多数OO语言都不能自然的表达这种关系。
fixopen() 09:41:42
你认为应该用什么来描述?
fixopen() 09:42:01
或者说,你认为继承的作用是什么?继承是用来干什么的?
狐狸发 () 09:42:19
子类应该拥有比父类更特殊的属性,普通三角形也有机会3条边都相等
一棵大白菜() 09:42:47
继承这个词可能会引起歧义,继承跟现实生活中的这个词含义是不同的
一棵大白菜() 09:43:03
代表泛化的反向
bighammer() 09:43:18
狐狸说的也很有道理:普通三角形也有机会3条边都相等 ,不过某个基类的作为一种派生类存在也是很正常的
fixopen(19710496) 09:43:22
按照你的说法,Window也可能有就是Button的机会,所以,Window派生出Button是不对的?
狐狸发 () 09:43:41
button有windows所没有的特性
fixopen() 09:43:46
有么?
一棵大白菜() 09:44:03
普通三角形也有机会3条边都相等那就是等边三角形啦,既是等边三角形,又是三角形
狐狸发 () 09:44:07
可以按,并触发一个事件
bighammer() 09:44:18
呵呵,可能我表达的有点不清楚,就是说普通三角形可以是等边三角形这一事实与OO里的继承不违背
fixopen() 09:44:25
一棵大白菜() 09:42:47
继承这个词可能会引起歧义,继承跟现实生活中的这个词含义是不同的
一棵大白菜() 09:43:03
代表泛化的反向
我也是这样认为的呀,继承就是特化嘛。
fixopen() 09:44:45
狐狸发 () 09:44:07
可以按,并触发一个事件
Window照样可以按,并触发一个事件。
狐狸发 () 09:45:18
我不这么觉得,我觉得等边三角形就是三角形并加上一个约束
一棵大白菜() 09:45:33
button是老婆奶头的父类
狐狸发 () 09:46:37
泛化和特例不光有继承的手法
还可以用分类的手法
fixopen() 09:46:48
现在你们就是不承认我们现在常用的OO语言有缺陷?
狐狸发 () 09:45:18
我不这么觉得,我觉得等边三角形就是三角形并加上一个约束
这句话说得太多了,事件所有的继承都是如此。
人是哺乳动物加上一些约束定义的。Button是Window加上一些约束定义的。
fixopen() 09:47:03
太多了-->太对了。
狐狸发 () 09:47:16
普通window不能成为一个button
狐狸发 () 09:47:32
button拥有普通window不具备的特性
fixopen() 09:47:34
在我看来,继承就是分类。
fixopen() 09:47:50
普通哺乳动物也不能成为一个人。
狐狸发 () 09:47:56
那你就这样认为好了
fixopen() 09:48:19
人也拥有普通哺乳动物不具备的特征。
狐狸发 () 09:48:52
人并来就是哺乳动物的子类
++oeqe() 09:49:08
button也室window的子类啊。。
狐狸发 () 09:49:38
这我也承认啊
狐狸发 () 09:49:51
我没说button不是window的子类吧
狐狸发 () 09:50:16
但是一个4边相等的window是window的子类吗
++oeqe() 09:50:36
这个属于数学集合论的范畴
bighammer() 09:50:43
这跟矩形与多边形得例子有什么区别
一棵大白菜() 09:50:52
你说为什么不是?
狐狸发 () 09:51:14
因为没人定义4边相等的window是一个特例,所以你没感觉吧
fixopen() 09:51:38
我怎么不知道你在说什么呢?
fixopen() 09:51:52
Window有四边不相等的么?
一棵大白菜() 09:51:57
没人用当然就没人定义
狐狸发 () 09:51:59
这和等边三角形一样,如果没人把等边三角形定义为一个特例,你也不会有继承的关系吧
狐狸发 () 09:52:13
你也不会觉得有继承的关系吧
fixopen() 09:52:38
关键是,你用继承表达什么?
狐狸发 () 09:52:45
这只是经验行为,而不是演化
fixopen() 09:52:52
是不是表达一个集合的特定子集?
fixopen() 09:53:07
继承用来表达演化?
狐狸发 () 09:53:23
继承就是演化啊
fixopen() 09:53:23
这是你说的呢,还是公认的?
一棵大白菜() 09:53:33
代表特化,跟模板本质一样
狐狸发 () 09:53:46
基类->派生类
这就是一种进化
一棵大白菜(301464) 09:53:33
代表特化,跟模板本质一样
狐狸发 (99643412) 09:53:46
基类->派生类
这就是一种进化
狐狸发 () 09:54:23
如果你认为是一种子集,那么未知的子类怎么考虑呢
狐狸发 () 09:54:37
他现在根本不在集合里
fixopen() 09:54:39
那么,你觉得人是哺乳动物概念的演化么?
狐狸发 () 09:55:02
当然是
狐狸发 () 09:55:30
应该说人是某种哺乳动物进化而来
狐狸发 () 09:55:56
应该说人是某种哺乳动物进化而来
所以人继承了哺乳动物的特性
fixopen() 09:55:59
莫非我们对哺乳动物研究的越深入,我们对哺乳动物的概念越清晰,结果,哺乳动物就是人?
狐狸发 () 09:56:37
看来你对演化的词理解有问题
狐狸发 () 09:57:00
人可以是哺乳动物,但哺乳动物不一定是人
fixopen() 09:57:28
stop,我看到你又在引入一个概念叫作进化,继承是表达进化还是演化。
或者,你说得演化就是进化?
我还以为你说得演化是我们对概念感觉的变化呢。看来你想表达的是进化:)
一棵大白菜() 09:57:35
就是建模的详细程度,不管你认识是否足够
狐狸发 () 09:58:04
好吧,我们就把这个词确定为进化
炮炮() 09:58:30
Evolution Complete!
fixopen() 09:58:37
我同意大白菜。
不同意狐狸发。
我认为狐狸发在某种程度上属于偷换概念。
一棵大白菜() 09:59:25
关键是:分歧在哪里?我都没搞明白
fixopen() 09:59:24
如果是进化的话,你认为形状可以进化为三角形?
fixopen() 10:00:12
我们对形状建模的越详细,它就越是三角形?
狐狸发 () 10:00:28
我说了,有些概念用继承来描述并不好
而不是所有的东西都用继承来描述
一棵大白菜() 10:01:03
我们对形状建模的越详细,越能代表多的特例三角形类别
狐狸发 () 10:01:06
象模板特化就不是继承关系
fixopen() 10:01:13
我知道用现在的OO语言的继承来描述不好,可我说得是:我认为现在的OO语言有缺陷。
狐狸发 () 10:01:28
这更偏向与分类
一棵大白菜() 10:01:28
用词不同而已
fixopen() 10:02:13
麻烦你仔细看看我的初始描述。
fixopen() 10:02:45
继承,类不变性之间的关系是不是很亲密?
继承仅仅表达为增加特有的属性是不是不够完善?是不是还要有对已有的属性进行限制的能力才完善?类不变性可以非常自然的为heir增加parent原有属性的限制。
考虑多边形与矩形的继承关系。矩形就是边数为4,相邻边正交的多边形。可惜的是,如果没有对多边形原有属性的限制,很难表达这种继承关系,也导致了很少有人这样使用继承,非常自然和直观的继承。
狐狸发 () 10:02:53
麻烦你看看我最早的回复
fixopen() 10:03:23
我知道你的回复,你说最好不要,我认为用继承是自然的,而你认为不是。这就是分歧。
一棵大白菜() 10:03:43
对已有的属性进行限制?有此功能啊
狐狸发 () 10:04:20
我的观点是,有些概念并不是自然的,是人为经验化的,这样用继承去描述就很牵强
一棵大白菜() 10:04:24
子类可修改继承自父类的行为
一棵大白菜() 10:04:35
就是变异
问题点数:0、回复次数:72Top
1 楼fixopen(dup)回复于 2006-07-18 15:18:26 得分 0
++oeqe() 10:04:42
子类不一定变异
一棵大白菜() 10:05:13
那也正常
fixopen() 10:05:25
比如:我有一个类,叫做Number,表示数字,然后我派生出两个字类,一个是Real,一个是Integer,Integer又派生出数个子类:Short,Int,Long,……
这样行么?如果不能用继承表达,为什么?继承不应该表达这些概念?为什么?
狐狸发 () 10:07:16
所有的数都是real的,别的数都是特例,比如integer就是没有小数的real,short,int,long更是计算机学科的经验行为的产物
fixopen() 10:08:41
所有的数都是real的对么?
是不是应该说所有的数都是complex的才对?
问题的关键是:你是不是认为计算机学科的概念是人为的,而别的是自然的?
狐狸发 () 10:09:37
这就是分类的粒度了,数学上这些分类也是按领域划分的
fixopen() 10:11:20
我没有搞清楚的另一点是:
究竟是你所谓的自然的概念该用继承表达呢,还是人为经验化的概念?
狐狸发 () 10:12:19
我没说一定要用那种形式,我只是说有的情况下继承并不适合
一棵大白菜() 10:13:23
自然的,是人所认识的自然
一棵大白菜() 10:13:42
不是自然固有的,但可能非常接近
fixopen() 10:14:15
我看OO在你那儿成为一个完全经验的,没有一定之规矩了。呵呵。
一棵大白菜() 10:15:26
非常接近,就是越有可能准确,所以有规矩啊,不过需要发现和学习
狐狸发 () 10:15:36
当然,人的认识的定有人为的因素
不过象数学就是人为的经验化的成分比较大,基本上都是人为的
而一些自然学科不同,它自然存在,不以人的意识为转移,他们的知识性就不不同
fixopen() 10:16:27
你认为:人从哺乳动物继承究竟行不行,对不对,合不合理?
为什么合理,或者不合理?
狐狸发 () 10:17:03
可以啊,从自然进化的角度看,人就是从哺乳动物继承的
一棵大白菜() 10:18:10
那也是人为分类,可以有其它分法,比如四肢动物,n肢,翅膀.....
++oeqe() 10:18:38
学习哲学吧
fixopen() 10:18:44
我怎么总觉得进化跟概念的演化不是一回事啊。
狐狸发 () 10:18:47
但那就不是继承关系了
++oeqe() 10:19:01
进化是变异
狐狸发 () 10:19:17
我刚才说了,为了避免混淆,现在只用进化,不用演化
一棵大白菜() 10:21:34
说过了,不能用现实的继承(进化,退化)来理解语言的继承特性(泛化,特化)
fixopen() 10:21:45
可是你用进化更让我感觉混淆。
你觉得图形派生出三角形可以么?应该么?合理么?
为什么合理或不合理?
如果合理,这儿也是用进化说事?
一棵大白菜() 10:22:38
或者大家说服委员会改一个词
狐狸发 () 10:22:48
我说了不要用继承派生去讨论这个图形->三角形的问题,你非得较这个劲么
fixopen() 10:25:44
狐狸发 () 10:22:48
我说了不要用继承派生去讨论这个图形->三角形的问题,你非得较这个劲么
为什么?OO在图形学领域应用的非常广,几乎可以说是唯一一个完全成功占据绝大优势的领域,不应该谈论它?
你认为继承主要用来干啥?
一棵大白菜() 10:27:04
不是区别,是关系
狐狸发 () 10:27:17
是三角形 -> 等边三角形
哺乳动物 -> 人的区别
问题被你扯远了
fixopen() 10:27:40
可是对于下一个,你就愿意说继承,说进化。
对于上一个,你不愿意说,为什么?
一棵大白菜() 10:27:55
因为不是生物
一棵大白菜() 10:29:06
继承和进化仿佛有点时间变化的意思
狐狸发 () 10:29:08
因为等边三角形就是三角形啊,只是属性特殊,他并没有普通三角形没有的东西
你要比的话就应该用普通人 -> 刘翔来比较,看看这是不是改用继承来描述
fixopen() 10:29:24
我们一步一步来。
我现在想说的是:
图形跟三角形可不可以继承?
狐狸发 () 10:29:41
是不是刘翔破了世界纪录就变成了新人类了
狐狸发 () 10:30:55
这应该用分类更合理,刘翔属于世界冠军这个类别
bighammer() 10:31:46
应该多继承的
bighammer() 10:31:56
现实世界的东西有各种属性
bighammer() 10:32:22
从不同方面看有不同的东西,所以还是JAVA的那个实现多个interface比较好
一棵大白菜() 10:32:57
谁用面向对象实现过树结构?
bighammer() 10:33:19
STL里不就有吗
狐狸发 () 10:34:20
另外我觉得,是否符合现实的继承和是不是用继承方法来编程也要区分一下
有时候并没有继承关系的事物也会用继承的办法来实现
fixopen() 10:34:20
我看不到问题有进展:(
狐狸发 () 10:34:47
那只是编程手法而已
一棵大白菜() 10:34:53
所谓的太空程序员
bighammer() 10:35:24
狐狸说的是一个事实,用那个实现的按理说不应该用public继承的
bighammer() 10:35:43
但是图方便,还是很多人这么用,即使是很好的产品,开源项目中也有
狐狸发 () 10:35:53
程序员需要解决的只是现实中很少的一部分问题,所以有些事情就不用那么深究了
狐狸发 () 10:37:25
不过越是大型复杂的系统,要考虑的合理性就越多,这样才会减少不必要的信息丢失
bighammer() 10:37:36
这样的讨论还是正式点写个长一点的帖子效果好些
bighammer() 10:38:03
即使是我们所关注的那不分,也会以多重面貌出现Top
2 楼fixopen(dup)回复于 2006-07-18 15:19:12 得分 0
狐狸发 () 10:44:34
好吧,确认一下,你要讨论的是OO的继承,还是OOP的继承,还是C++的继承,他们是有些不一样的
狐狸发 () 10:45:57
C++里还有public private virtual继承,这也是有区别的
fixopen() 10:47:27
我要讨论的是PL(Programming Language)的继承,我认为现在的常用语言的继承是有问题的。
fixopen() 10:48:01
不能够自然的直观的表达现实世界。或者说表达我心目中的概念。
狐狸发 () 10:48:07
那就是OOP的继承了,是吗
fixopen() 10:48:14
是的。
狐狸发 () 10:49:12
那好,OOP是为了program服务的,他为了特定领域服务决定了它不是一个适合泛化领域的工具,你觉得呢
++oeqe() 10:50:25
开发基于dna的继承语言哈哈,那么你的继承将会具有真实自然界的继承了。。
fixopen() 10:50:41
特定领域服务?你认为Program是特定领域?
狐狸发 () 10:51:06
当然是了,你不觉得吗
fixopen() 10:52:16
我不这样认为,我认为Program是创建一个现实世界的镜像(当然是模型化,理想化的镜像)。它创建那个领域的镜像,就是那个领域的。
++oeqe() 10:53:11
这样的要求太高了吧,就像共产主义一样。。。
狐狸发 () 10:53:14
program又不是写小说,可以天马行空那么自然,他要为计算机学科服务的,随便写写的东西只能是伪代码,它注定要受到计算机学科发展的限制
狐狸发 () 10:53:55
你可以有理想,但是不能逃避现实啊
fixopen() 10:53:55
呵呵,我才不认为Program是为计算机学科服务,反过来,我认为Program是为各行各业服务。
狐狸发 () 10:54:27
各行各业的交叉部分就更特殊了
++oeqe() 10:54:27
program只是计算上的游戏
++oeqe() 10:54:52
服务是通过计算机完成的,你的program不可能脱离和超越计算机本身的能力
狐狸发 () 10:55:19
要抽象所有行业的现实,那就不是OOP了,那是纯OO了
狐狸发 () 10:55:59
那么我刚才讨论的进化表现为继承的观点就是这个方面的
fixopen() 10:57:33
可是你没有让我明白。我现在还是对你的进化既是继承感觉的迷惑不堪。
狐狸发 () 10:59:37
进化是旧事物发展成了新的事物,这是一个群体之间的区别,同一个群体之间不应该讨论是否进化了
狐狸发 () 11:02:45
比如古代猿发展出了猴子,人,现代猿,狒狒,那么这个是进化,他们存在继承关系,但是灵长目只是一个分类,灵长目和猴子是从属关系,并非进化关系
fixopen() 11:04:11
如果说我在研究三角形,刚开始我对三角形一无所知,我只知道它是一个object,一个东西而已。后来我发现它其实可以被划归为Shape这个类型,它是一个形状,它自然仍然是一个object。最后,我发现它可以更特殊,它是Trishape,三角形,这不影响它是一个Shape,也不影响它是一个object。
这个关于三角形的研究,导致我对它的知觉的进化(我更愿意称为演化),用继承描述是非常合理的。
可是如果我研究的是一个手绘的一个不知名的封闭曲线,我要是能从中得出三角形这个概念,那显然就是瞎扯了。但是不影响我认为它是一个形状。
现在开始正题,我研究一个变形虫,然后发现它是动物,我能进化成人么?可以么?有效么?合理么?
狐狸发 () 11:05:54
你这里有问题,某个进化成为人,和某个事物一定能进化成人没有必然关系
fixopen() 11:07:07
那你的继承区分这两种进化么?
fixopen() 11:07:32
或者说,你是不是用进化来描述变形虫和人的关系?
狐狸发 () 11:07:41
关系并不代表过程,我觉得你这里有误解
fixopen() 11:08:36
进化是关系还是过程?
你的继承表达的进化是关系还是过程?
狐狸发 () 11:09:21
A是B进化而来的,你觉得这是关系还是过程
fixopen() 11:10:14
我想知道的是你的进化是关系还是过程。
我自然认为是过程,可是你用继承这种关系表达,所以我困惑。
狐狸发 () 11:10:50
我认为是关系
B进化成为A,这句话中才是过程
fixopen() 11:11:43
好,变形虫跟人是不是有进化的关系?
fixopen() 11:12:11
人是不是可以继承自变形虫?
狐狸发 () 11:12:14
根据目前的知识参考是这样的
乡长<还有个娃>() 11:12:33
fixopen() 11:12:14
人是不是可以继承自变形虫?
不是继承
狐狸发 () 11:12:49
不过中间有别的物种传递,你漏掉了很多信息
乡长<还有个娃>() 11:12:52
在继承的过程中还有变化,但是继承会全包进来
狐狸发 () 11:13:19
应该是变形虫->....->人
fixopen() 11:13:53
唔,我明白了,可是我坚决反对这样的继承。
Top
3 楼fixopen(dup)回复于 2006-07-18 15:19:54 得分 0
乡长<还有个娃>(89161617) 11:14:01
生物进化有dns转变的因素
乡长<还有个娃>() 11:14:15
但是程序里面的继承没有
狐狸发 () 11:14:35
事实上变性虫由细胞组成这一特性人也保留着,当然这一特性是变形虫继承别的生物而来的
狐狸发 () 11:16:13
你反对这种继承只是你不参与这样的活动,如果是研究进化的人可能就赞同这一点
乡长<还有个娃>() 11:17:06
no,继承和进化是两个概念
狐狸发 () 11:17:17
另外继承只是自然界关系中的一种,如果想把所有的信息都用这个关系抽象是不行的
狐狸发 () 11:18:07
的确是2个概念,我说得是OO理论中继承对应现实中
乡长<还有个娃>() 11:18:45
自然界不存在继承
狐狸发 () 11:18:49
并非说他们就是等价,其实这也是一种管中窥豹而已,信息也被简化了
乡长<还有个娃>() 11:19:07
所有的遗传都有变化,当然克隆除外
狐狸发 () 11:20:06
OOP中的继承是完全包含父类,OO的继承只是一种概念,并没有说继承的部分就一成不变
狐狸发 () 11:22:43
OO并不是万能的,也有适用的领域,程序员最后还要用OOP来实现,而人一般都是怎样好就选择怎样作,理论始终只是引导而已,不要成为枷锁
fixopen() 11:26:04
其实并不是没有语言支持我说的那种继承,Eiffel就非常完美的支持。可惜的是,大多数人都否认给属性增加限制不是继承应该干的事,悲哀啊。
狐狸发 () 11:29:28
我并不反对,但那只是一种手法,并没有体现继承的含义
fixopen() 11:29:27
上面的话说反了,否定句式比较难折腾。
fixopen() 11:29:58
我认为那体现了继承的含义。
因为我认为继承就是表达分类的,表达特化的。
狐狸发 () 11:30:57
那么0,1,2,3这个是不是都应该从整数继承呢,他们是整数的特化
fixopen() 11:32:34
如果有必要。
狐狸发 () 11:33:19
那你觉继承取决与是否必要,而不是一种理论或者是一种方法?
fixopen() 11:34:17
我觉得是否继承,不是继承本身。
继承就是特化,就是分类。
是否需要继承,也就是说,是否需要特化,需要分类,依赖于需要有否。
我说的明白么?
狐狸发 () 11:35:33
那么没有必要区分等边三角形,那么就不必从三角形继承了是吗
fixopen() 11:37:37
自然。
狐狸发 () 11:38:06
哦,那我明白了
fixopen() 11:43:28
但是一定不能阻止从三角形派生出等边三角形。
狐狸发 () 11:43:58
为什么,如果有人觉得没这个必要呢
fixopen() 11:45:00
没有就不用派生啊。这有什么问题么?
狐狸发 () 11:45:39
fixopen() 11:43:31
但是一定不能阻止从三角形派生出等边三角形。
这句话是什么意思呢
fixopen() 11:46:17
意思就是说,如果有人觉得有必要派生出等边三角形,就派生吧。
狐狸发 () 11:47:14
嗯,明白Top
4 楼mhzjy(菜鸟也是鸟)回复于 2006-07-18 15:24:32 得分 0
我要进老兵团 我是hunterTop
5 楼lexchou(龍子龍孫)(本人已死)(有事烧纸)回复于 2006-07-18 15:25:03 得分 0
路过Top
6 楼fixopen(dup)回复于 2006-07-18 15:27:25 得分 0
狐狸发 () 13:01:46
吃完饭了,无聊的消化中
刚才我看到你需要判断一个图形是否为三角形,你希望用继承机制来判断
而我大胆推测一下,是不是你也希望用继承机制判断一个三角形是否是等边三角形
fixopen() 13:04:22
判断?什么判断?
狐狸发 () 13:06:25
err,发送老是超时
狐狸发 () 13:06:59
找一端很小的发:
可是如果我研究的是一个手绘的一个不知名的封闭曲线,我要是能从中得出三角形这个概念,那显然就是瞎扯了。
狐狸发 () 13:08:26
你坚持用继承来做,我想是否你想用继承机制来获取三角形这个信息呢
fixopen() 13:14:10
不是。继承对我来说是类型之间的关系。三角形的信息依赖于三角形这个类型。
继承只是让我可以方便自如的重用类型而已。
狐狸发 () 13:16:51
好吧,我们说点实际的,如果我创建了一个手绘的图形,但不是以三角形类创建的,而事实上这个图形却是一个三角形
那么你是否能体现出图形和三角形类型的关系
fixopen() 13:19:29
我不太清楚你的意思,你是说你创建一个一个图形,但是这个图形其实是一个三角形是么?
狐狸发 () 13:20:06
恰巧是一个三角形
fixopen(19710496) 13:20:37
噢,理解了。
然后你关心什么?
狐狸发 () 13:21:06
关心你是否能正确的判断出他是一个三角形
fixopen() 13:22:22
可以没有什么悬念的说:这是一个图形。
至于它是不是一个三角形,还需要进一步的判断。
三角形是图形的特化,也就是图形集合的子集,那就是说,它属于图形这个集合,并不能保证它不属于三角形。
狐狸发 () 13:23:38
那么你怎么进一步的判断呢,你觉得三角形是图形的子集这点需要用继承来实现,我想知道这是不是有什么意义
fixopen() 13:25:06
这个图形是不是满足三角形所附加的约束条件呢?如果满足,它就是。
狐狸发 () 13:25:49
那好象跟继承没什么关系吧
fixopen() 13:26:30
比如:动物(类型)。动物都有食物(属性)。
子类型
食肉动物,食草动物,杂食动物。其实就是通过限制食物这个属性来进行继承的。
fixopen() 13:27:15
三角形这个类型的描述完全满足图形这个类型的描述啊。
fixopen() 13:14:10
不是。继承对我来说是类型之间的关系。三角形的信息依赖于三角形这个类型。
继承只是让我可以方便自如的重用类型而已。
狐狸发 () 13:28:41
那么你现在是否把这个图形作为特例的子集"三角形"来看待呢
fixopen() 13:32:38
看我是否有必要。我是把它当作图形来看的,所以我并不需要知道它是不是是三角形。
比如:
Parent* p = new Child();
这时候,我只是把p当成Parent来看的,这就是OO扩展性的基础,我可以做出来一个ApplicationFramework,它能够跟各种具体的派生出来的类型合作,原因就是我并不关心具体的特化类型是什么。
fixopen() 13:33:24
当然,如果我确实非常需要知道它是不是Child,这时候一般要采用各种手法来尝试了。
fixopen() 13:33:55
比如:Java的instanceof,C++的dynamic_cast,Eiffel的/=。
狐狸发 () 13:35:22
好那么我们来讨论C++吧,
比如三角形是Trishape,手绘是Handshape,那么你怎么把这个Handshape对应上Trishape
fixopen() 13:38:25
现在的问题是:Handshape跟Trishape是什么关系?
fixopen() 13:38:38
父子类关系?
fixopen() 13:38:49
互不相容的兄弟类关系?
狐狸发 () 13:39:06
他们有共同的基类shape
fixopen() 13:39:04
拥有交集的兄弟类关系?
狐狸发 () 13:41:16
补充说明一下,手绘图形可以是任意形状,当然也包括三角形
fixopen() 13:42:22
那你的意思是,Handshape可以是Trishape的父类啊。
狐狸发 () 13:42:44
好吧,也可以这么实现
fixopen() 13:46:18
hs,这是一个Handshape对象,假设它是Trishape。
我们可以这样试探
if (dynamic_cast<Trishape*>(hs))
//yes, it's trishape
else
//no, it's not trishape
狐狸发 () 13:47:02
nono,我创建的是一个handshape对象,而不是trishape
fixopen() 13:47:18
但是我说过,一般情况下,这种试探都是会影响OO的扩展性和重用性的。
狐狸发 () 13:47:46
你这样测下来结果说不是三角形
fixopen() 13:48:51
你创建的是一个Handshape,你为什么要关注它是不是trishape?
你的目的是什么?
我说我是一个人,这就行了,非得表明我是一个男人才行?要不要表明我是一个青年男人?Top
7 楼fixopen(dup)回复于 2006-07-18 15:28:27 得分 0
fixopen() 13:49:19
你的用意是什么?不想把Handshape当成Handshape用?
狐狸发 () 13:50:40
我想知道你怎样确定图形和三角形的关系啊
再说这个问题是有意义的,比如一个模式识别系统
fixopen() 13:51:48
大哥,模式识别系统不是类型系统,类型系统(尤其是我们现在讨论的类型系统),关注的是静态的关系,不是运行时识别。
运行时识别根本就是两码事。
狐狸发 () 13:52:34
哦,那么你的意思说运行期间识别就不用考虑罗
狐狸发 () 13:55:34
好吧,既然你这么说了,我也就认同吧
不过我还有个问题,关于三角形和等边三角形的,那么你创建等边三角形一定是用一个特别的类吧,那么我创建了一个等边三角形形,但是我改变了某个顶点的位置,那么他还是等边三角形吗
fixopen() 13:55:57
不要那么绝对,静态的类型安全是不够的。仍然需要动态的,这就是dynamic_cast存在的必要性。
但是动态类型系统还没有发育到模式识别的程度。
fixopen() 13:56:20
别的两个顶点都不改变?
狐狸发 () 13:56:29
不变
fixopen() 13:56:32
那是类型系统所不允许的。
狐狸发 () 13:56:55
为什么,等边三角形不能改变顶点位置吗
fixopen() 13:58:22
可以,但是要保证类型不变性,这也是一个类的基本特性,一个类一定要表达一个不变的东西。
fixopen() 13:59:01
不变量的保证要求你修改一个顶点的时候,别的定点一定需要同时修改。
狐狸发 () 13:59:41
哦?这样我岂不是不能修改等边三角形了,那可不太好啊
fixopen() 14:00:07
能啊。
fixopen() 14:00:11
怎么不能呢?
狐狸发 () 14:00:44
怎么改呢,我就需要把只修改等边三角形的某一个顶点
狐狸发 () 14:01:56
另外,维持重心不变只是一个功能,不是等边三角形特有的吧
fixopen() 14:02:10
class LINKED_TREE [G] inherit
DYNAMIC_TREE [G]
rename
empty as ll_empty
export
{NONE} ll_empty
undefine
child_after, child_before, child_item,
child_off
redefine
parent
select
has
end
LINKABLE [G]
rename
right as right_sibling,
put_right as l_put_right
export
{ANY} put, replace
{LINKED_TREE} l_put_right, forget_right
undefine
copy, is_equal
end
LINKED_LIST [G]
rename
active as child,
put_left as child_put_left,
put_right as child_put_right,
after as child_after,
back as child_back,
before as child_before,
count as arity,
cursor as child_cursor,
duplicate as ll_duplicate,
empty as ll_empty,
is_empty as is_leaf,
extend as child_extend,
extendible as child_extendible,
fill as ll_fill,
finish as child_finish,
first_element as first_child,
forth as child_forth,
full as ll_full,
go_i_th as child_go_i_th,
go_to as child_go_to,
has as ll_has,
index as child_index,
isfirst as child_isfirst,
islast as child_islast,
item as child_item,
last_element as last_child,
make as ll_make,
merge_left as ll_merge_left,
merge_right as ll_merge_right,
new_chain as new_tree,
off as child_off,
prune as ll_prune,
put as child_put,
readable as child_readable,
remove as remove_child,
remove_left as remove_left_child,
remove_right as remove_right_child,
replace as child_replace,
search as search_child,
start as child_start,
writable as child_writable
export
{ANY}
child
{NONE}
ll_make, ll_has,
ll_merge_left, ll_merge_right,
ll_fill, ll_duplicate, ll_full, ll_empty
undefine
child_readable, is_leaf,
child_writable,
linear_representation,
child_isfirst, child_islast, valid_cursor_index,
copy, is_equal
redefine
first_child, new_cell, new_tree, child_cursor
select
is_leaf
end
你看一下一个继承,这是一个class的头,描述了类名和继承。
fixopen() 14:02:47
invariant
no_void_child: readable_child = child_readable
这是一个类尾,描述了类的不变量。
狐狸发 () 14:02:50
看不懂,我只会C++耶
信仰迷离(510857) 14:02:59
狐狸发 () 14:04:29
我现在就想修改等边三角形的某个顶点,然后你说因为某个不变量导致这种行为是被禁止的,但是我用很多绘图软件都可以啊
fixopen() 14:05:48
我说的还不明白?你修改一个顶点,必须同时修改另外两个顶点。
fixopen() 14:06:10
我没有说不允许你修改啊。
狐狸发 () 14:07:22
为什么不允许只修改一个顶点呢,我记得等边三角形没这个限制啊
fixopen() 14:09:40
难道你可以修改一个等边三角形的一个点的位置?不修改别的位置?
它还是一个等边三角形么?
狐狸发 () 14:10:31
不可以吗?修改完变成一个等腰三角形啊,这很正常
fixopen() 14:11:15
哥们,你那是等边三角形么?
你是在考虑类型呢?还是在考虑运行时呢?
fixopen() 14:12:07
你别跟我说那些行么?那是你用三角形这个类的对象的时候,不是你用等边三角形这个类的对象的时候。
狐狸发 () 14:12:28
关键不是在这里吧,你的设计导致等边三角形很难变成普通三角形
fixopen() 14:13:04
根本就不允许。变成非等边的普通三角形,还是等边三角形么?
fixopen() 14:13:31
如果你不想限制是等边三角形,你用三角形好了,有人阻拦你么?
fixopen() 14:13:38
你指望类型系统给你干啥?
狐狸发 () 14:13:56
为什么要维持他是等边三角形?我就是要变掉它
再说不光是等边三角形,别的图形也可以在维持重心不变进行修改啊
fixopen() 14:15:18
算了,我觉得讨论的问题已经跟继承和类型系统没有任何关系了,打住。Top
8 楼fixopen(dup)回复于 2006-07-18 15:28:56 得分 0
狐狸发 () 14:17:28
当然有关系,我认为类型系统确定到三角形就可以了,没必要继承出等边三角形,等腰三角形,只是应用层加个模板方便创建就ok了,你要维持等边的特性不变,可以增加维持重心不变进行修改的功能,而且更通用,更合理
fixopen() 14:21:57
呵呵,这个问题可以讨论,可是这个问题我们以前已经讨论过了。
结论就是:
看需要。如果需要就制造一个等边三角形的类型,如果不需要就不制造。
这跟我们刚才讨论类是不是必须位置自己的不变性没有任何关系。
fixopen() 14:25:23
位置->保持。
狐狸发 () 14:25:56
那么这个需要不是针对性很强么,需要一个一直维持的等边三角形,如果可变那不是更适用?你难道不希望代码适用范围更广?
fixopen() 14:26:27
那你为什么需要三角形?多边形是不是适应性更强?
fixopen() 14:26:47
为什么需要多边形?图形是不是适应性更强?
fixopen() 14:26:58
为什么需要图形?对象是不是适应性更强。
狐狸发 () 14:27:07
是啊,N边形是很灵活地,很多矢量绘图软件都是这样做
狐狸发 () 14:28:03
提供的正方形,三角形,5边6边形都是模板,而不是特有的类型
fixopen() 14:28:13
我也没说关于灵活性的话呀,我关注的是类型之间的父子关系或者说继承关系。
这个灵活有关系么?
你要觉得没有必要,完全可以不制造啊。
狐狸发 () 14:28:46
你觉得等边三角形和三角形是父子关系吗?
fixopen() 14:29:17
我觉得可以是。
fixopen() 14:29:30
至少是祖先和子孙的关系。
狐狸发 () 14:29:41
那只是子集吧
fixopen() 14:29:41
我的意思是说不一定是直接继承。
fixopen() 14:29:52
别忘了,我的继承就是特化,就是子集。
狐狸发 () 14:30:10
但不是父子关系
狐狸发 () 14:31:00
也不是祖先关系,那只是你方便编程的手法,没有实际的继承的意义
fixopen() 14:31:01
fixopen() 14:29:17
我觉得可以是。
fixopen() 14:29:30
至少是祖先和子孙的关系。
这是我的看法,我已经说得很清楚了。
fixopen() 14:31:46
你可以有自己的看法,而且关于你的进化观,我是不同意的,你自然也可以不同意我的分类观。Top
9 楼mhzjy(菜鸟也是鸟)回复于 2006-07-18 15:41:23 得分 0
go onTop
10 楼pomelowu(羽战士)回复于 2006-07-18 16:02:06 得分 0
老婆,和牛魔王出来看上帝Top
11 楼fixopen(dup)回复于 2006-07-18 17:51:54 得分 0
前面说的:
fixopen() 13:33:55
比如:Java的instanceof,C++的dynamic_cast,Eiffel的/=。
有误导之嫌,Eiffel是?=。Top
12 楼steedhorse(晨星)回复于 2006-07-28 15:35:42 得分 0
偶也来看上帝了,看完之后,写一本章,奏曰:
在OOP中,对象的“不变性”(Invariant)很重要,组合也好,继承也好,都不能违反它,所以OOP中所说的“继承”虽然说表达的是“IS-A”的关系,但跟现实中或其它自然科学中所说的“IS-A”却不可能完全等同。原因就在于OOP对“不变性”的强调。
我习惯用“图形”,“矩形”和“正方形”的关系来讨论这个问题。矩形是一种图形,于是在实际编程中我们经常让矩形类从图形类派生,但虽然正方形也是一种矩形,我们却不太会让正方形从矩形派生。
为什么?其实我觉得问题很简单的,无非是因为我们实际项目的需要呗。我们对一个“图形类”的要求并不高,通常就定义这么几个方法就够了:move,draw,getArea……,这些矩形在不改变其不变性的前提下都能做到,所以我们也常让矩形从图形派生。
但一个矩形,却往往需要有:setWidth,setHeight诸如此类的方法,改变其中一组对边的长度,另一组边不变,这对于正方形来说,在不改变对象的不变性的前提下,是做不到的,于是我们就不会让正方形从矩形派生。
但这一切当然不是绝对的,让我举个无聊的例子:假如我想让一个“图形”类支持一个cut方法:
void cut(Position pos, int degree)
要实现的操作是,经图形上的pos点画一条倾斜角为degree的直线,并切掉图形的位于直线“上方”的部分。这对一个图形来说,当然没任何问题,切了之后,它还是个“图形”,仍然可以move,draw,getArea。但支持这样一个方法的“图形类”,还可以从它来派生出矩形吗?不可以了。
而正方形就一定不能派生自矩形吗?也未必,假如我要编的软件中,任何图形创建后都不会有任何改变(只读图形,嘿嘿),也就是矩形根本不需要setWidth/setHeight这些方法,那从我的矩形类为什么不能派生出正方形呢?完全可以。
所以,“矩形可以从图形派生,而正方形则不能从矩形派生”只是一种假象,或者至少不是绝对的。之所以会造成这种假象,原因仅仅是我上面的这两个反例非常生僻而已。但生僻归生僻,作为理论讨论的时候,反例就是反例。
再所以,任何两个类之间,究竟可以不可以有派生关系,虽然也要看它作为一个模型所反映的现实事物之间的联系,但最终还是要看它都具体反映了事物的哪些属性。现实事物有很多属性,经常的情况是,如果一个类可以从另一个类派生,那也常常是因为它们只反映了现实事物的一部分而已。
其实数学中说正方形是一种矩形,主要原因也是因为数学研究中不强调“对象”的概念,也就不需要强调对象的不变性。
数学上,满足两个条件就可以说一个平面图形是矩形:
(1)是个平行四边形;
(2)有一个直角。
这时,对于这个定义来说,正方形既充分,又必要,所以我们就说正方形是一种矩形(仔细想想这里边有明显的“静态”味嘛,人家只说是正方形就是矩形,别的啥也没说)。
但假如数学上也强调对象和不变性的话,那就未必了。比如矩形至少保证自己是个平形四边形,而且有直角(这些就是它的“不变性”),正方形除此之外还保证邻边相等。那么,假如这样定义矩形:
(1)是个平行四边形;
(2)有一个直角。
(3)改变某组对边的长度不影响该图形的所有不变性
那显然正方形根本不是矩形。Top
13 楼steedhorse(晨星)回复于 2006-07-28 15:44:12 得分 0
XML Schema中,定义元素类型时,同时支持扩充继承和限制继承,但我觉得那是因为XML终究不是一种编程语言。这里边的对象只有“属性”,没有“行为”。
而程序设计语言却必须在“行为”上做精心设计,所以“限制继承”,我觉得可能用处不大,或者实现的复杂度太高。
现有的OOP语言中所支持的继承虽然从这个意思上讲不是一个完美的继承机制,但它正是由于坚持“接口的不变性”,比如通过对重载方法时“前条件更宽,后条件更严”的要求,大大方便了我们的程序设计。
如果没有这些要求,那反倒可能会使OO的功能大打折扣,至少就偶目前的经难感觉是这样。Top
14 楼steedhorse(晨星)回复于 2006-07-28 15:47:29 得分 0
臣 晨星 丙戌年七月初四日
^0^Top
15 楼cunsh(村少)回复于 2006-07-28 16:13:52 得分 0
markTop
16 楼sjjf(水晶剑锋)回复于 2006-08-03 02:01:30 得分 0
看了前面一段,不过实在没有勇气看完,太长了。
面向对象思想来源于分类学理论。
你们讨论的问题好像是抽象和划分。
在进行阐述我的理解之前,先看几个概念的定义(以前学习时候的笔记)。
客体: 客观存在并可观察到的事物,也包括想象产生的事物.任一客体都具有众多特性.
(可以认为这些客体就是这些特性的集合).
概念: 根据一群客体所共有的特性形成某一概念.
(可以看作特性的集合,这些特性是集合空间里面的所有客体共有的)
内涵:一个概念所反映的客体的全部特征称为概念的内涵。
外延:一个概念所指客体的范围称为概念的外延.
抽象:抽取事物的共有特性将其概括为概念的过程.
划分:同一概念可以依据不同的分类标准(这些标准也叫做维度)划分为若干个不同的概念组.
(分类标准就是集合论里面的等价关系--自反,对称,传递)
继承是一种特化关系,它刚好和抽象相反,
抽象是一种泛化关系.这两种关系在集合论里面是偏序关系(自反,反对称和传递的)。
在进行讨论继承之前,先讨论讨论抽象。因为继承依赖的模型来源抽象的过程。
抽象的过程是自底向上的。
给定一个集合空间,空间里有5个元素,
比如都是由三条直线线段组成的封闭的东西。
A(10,20,15)
B(15,15,20)
C(10,10,10)
D(11,12,13)
E(30,30,31)
A-E都是客体,每一个客体都若干相同的特征如
1.都是直线段
2.直线段的数目是三个
3.三条线段每一条的两端都和分别和另外两条的一端相连。
假设就抽象出这么些特征吧。我们把这些特征集合称作一个叫三角形概念。
注意三角形这个东西是一个抽象的东西,没有任何的实体。
如果没有别的需要,这样的抽象就够了。
直接实例化就是需要的客体了。
但是你们觉得不够用,然后在这一层概念上,
你们尝试做一种划分,
根据等价关系 每两条鞭相等 划分出等价类,
{三条边都相等三角形--等边三角形}
{两条边都相等,但不等于第三条边三角形-- 等腰非等边三角形}
{三条都不相等的三角形 --非等边非等腰三角形}
这三个概念是并列概念。
是属于三角形这个上位概念的下位概念。
也可以说是三角形的外延。
三角形和等边三角形的关系是层级关系,确切地说是层级关系中的属种关系。
可是另外一些人尝试了另外一个划分。
根据等价关系 三条边都相等 得到了另外一个划分
{三条边都相等三角形--等边三角形 -- 等边三角形}
{不是三条边都相等的三角形 -- 非等边三角形}
这两个子概念是三角形的得下位概念,同上一个的分析。
他们对这样的划分还不满意,所以对非等边三角形进行再次细化。
比如依据等价关系 两条边相等 划分出
{等腰三角(实际上在上位概念的限制下,是等腰非等边三角形)}
{非等腰三角(实际上在上位概念的限制下,是非等腰非等边三角形)}
这样得到的是两个不同的分类体系。
哪个合理,哪个不合理没有定论,根据不同的专业领域和研究需要而定,如steedhorse(晨星) 所说。
而且得到分类的体系的方法有几种
一种是纯自顶向下的。
一种是纯自底向上的。
一种是混合的,上下求索。
你们讨论的分歧,个人觉得是概念有重叠了,也就是讨论的东西不是在同一个划分标准下。
举个形象的例子,如果三角形还有颜色的话,如集合空间变成
A(10,20,15,红)
B(15,15,20,黄)
C(10,10,10,绿)
D(11,12,13,红)
E(30,30,31,黄)
那么上面的第一个种类体系中在
三角形的概念下,还存在一个另外一个维度的划分。
等价关系:颜色相同
{红颜色的三角形}
{黄颜色的三角形}
{绿颜色的三角形}
你们的讨论我觉得像问红色的三角是不是等边三角形一样。
在不同的标准下是没有可比性的。穿红色内裤的人和好人没有关系。
虽然超人是好人。
Top
17 楼sjjf(水晶剑锋)回复于 2006-08-06 23:58:04 得分 0
在c/cpp灌了半个月,觉得只有这个帖子算得上是对oo思想的认真思考。
希望下次来的时候能够听到不同的声音。
Top
18 楼fixopen(dup)回复于 2006-08-09 23:45:56 得分 0
引用:
但一个矩形,却往往需要有:setWidth,setHeight诸如此类的方法,改变其中一组对边的长度,另一组边不变,这对于正方形来说,在不改变对象的不变性的前提下,是做不到的,于是我们就不会让正方形从矩形派生。
呵呵,这儿正好是我要强调的,我认为现代的OO语言(除了Eiffel),对于继承的支持都太差,都不能支持不变性的协变。比如:正方形继承自矩形,那么正方向首先要维持矩形的不变性,比如:对边平行且等长,临边正交。同时,正方形可以增加不变性要求,比如:临边等长。
而你上面说的setWidth,setHeight一样可以用。只是它们在正方形这个类里面,除了要维持矩形的不变性以外(比如,setWidth要同时修改两条边的长度,保持对边想等等等),还要维持作为正方形必须维持的不变性(临边也相等,这就意味着setWidth同时要修改4条边)。
这才是我上面说的那么多东西的一个应用。Top
19 楼fixopen(dup)回复于 2006-08-09 23:56:46 得分 0
引用:
那么上面的第一个种类体系中在
三角形的概念下,还存在一个另外一个维度的划分。
等价关系:颜色相同
{红颜色的三角形}
{黄颜色的三角形}
{绿颜色的三角形}
你们的讨论我觉得像问红色的三角是不是等边三角形一样。
在不同的标准下是没有可比性的。穿红色内裤的人和好人没有关系。
虽然超人是好人。
显然你的说法无可非议,但是很明显你说的跟我们争论的焦点没有关系,你的这个我认为涉及到多继承的问题。每一个维度都可以做一个分类。比如,穿红内裤的,穿黄内裤的,跟好人,坏人,再跟男人,女人……这几个分类体系下,我想表达穿红内裤的好男人,这时候是不是应该用多继承?如果是,我们的OO语言应该如何设计以便于能够自然的支持多继承?如果不是,我们应该怎么表达这个关系?Top
20 楼steedhorse(晨星)回复于 2006-08-10 09:33:20 得分 0
对于正方形和矩形这样的例子,我还是觉得关键问题在于程序设计语言中的对象是一个同时拥有属性和方法的“活的”有机体,并因此衍生出“生命周期”,“状态转换”这些概念或过程,所以它不能直接跟数学或逻辑学上的一些只强调属性的概念及其关系做直接的映射与比较。
再退一步说,一个类究竟要怎么设计,毕竟还是看应用场合的具体需要。比如从来没有什么标准来规定一个“Shape”类究竟该怎么设计,没有标准规定它必须(或必须不)拥有哪些属性,方法,满足什么样的不变性,达到什么样的异常安全程度等等,在这种情况下,从程序设计的角度,如何能一口断定Rectangle能或不能从Shape继承呢?或许张三设计的Shape类很容易派生出Rectangle,而李四设计的则几乎办不到。
当然,我们可以说,“至少不应让Rectangle派生自Shape成为不可能”,以此来显示语言特性模拟现实世界的能力。那我前面也提到了:Square完全“可以”从Rectangle派生,主要还不是取决于Rectangle类是如何定义的(逻辑接口与不变性)。
既使不谈这些特别的例子,我们回到更一般的问题上:“设计一个可被继承的类”是一件很简单的事吗?当然不是,不管是图形类还是其它什么类,都不是。它至少比设计一个没打算被继承的类要考虑得多很多。Top
21 楼sjjf(水晶剑锋)回复于 2006-08-11 01:14:39 得分 0
to fixopen
=====================================
这才是我上面说的那么多东西的一个应用。
=====================================
没太明白,所谓的不变性不就是共性么?
争论的焦点不是讨论继承是什么么?偶贴的内容是关于继承的机制的。
目前我还没有能力把它们系统化,或者是说目前只能用来解释一些简单的现象。
如果要达到那一步,需要一些时间的沉淀。
关于多重继承,没做过思考,我拿不准我要表达的东西是否能经得起推销,暂时保留,
渡完假如果有时间再来这里忽悠你,哈哈。
to steedhorse(晨星)
继承,抽象应该是关于系统的静态结构机制的。
“生命周期”,“状态转换”刻画系统的动态行为的。
它们侧重点不一样。层面也不一样。
================================================
比如从来没有什么标准来规定一个“Shape”类究竟该怎么设计,
================================================
这点倒是真的,机制不是策略,机制只是告诉你我提供了这些东西。
如何把这些东西有效的用起来,是策略的事情。
机制就像 加减乘除的运算,策略就像是解决工程问题的某种算法。
好的策略一定要紧扣机制的特点的。
策略可以变,但是机制是不变的(或者说几乎很少变)
如何设计一个合理的类体系,太难了,关键是问题域太复杂了。
我知道一点理论方面的知识,至于问为什么是这样子,我也不是很明晰,目前还无法回答。
我以前做的是遵循的 通用职责分配软件模式
其实更多的时候直接是参照现实中的具体或者抽象的概念形成类,做些适当的增减,合并,抽象。
(这是有道理的,日常生活中概念经过长时间锤炼,基本上和我们的类很相似)
具体的做法可以参照<uml模式应用>一书(这本书值得大力推荐),我是根据那里的方法论
完成我的第一个oo设计的。
在初期我以那本书为理论依据,找到类还不算难,构建的类体系比较冗余,
如果仅仅为了功能的话,可以用来写程序了,
但设计并不单单是要满足功能性了,还有可扩展性,可用性,可维护性 等要求,
为了这些特性,在中期,需要对系统的静态结构和动态行为进行改造,以达到我们的目的,
在进行oo设计的过程中,我必须要对自己做出的设计的作出解释,
比如“你为什么要这么样抽象,而不是那样抽象。你的依据是什么”
“你为什么要用这种模式,它能带来什么好处,适用范围是什么样的,它的效率是否太低?”
“我认为这样做比你那么做要好,....”
在不断的说服和被说服的过程中。迫使我去思考,什么是对象?什么是类?什么是抽象?什么是多态?
什么是关系?同是关联关系,为什么聚集和组合不一样?我为什么要用这种模式而不用哪种模式,
需要那些指标才能够做决策,做决策的模型应该是什么样的?
模式和模式之间可能会依据目标或者条件转变,它们之间的分界点在哪儿?
可否统一到一个描述模型里面?
他们必须可以用数学描述出来的,否则不足以说服人,初期我并没有知道这一点,
尽力的举一些生活中相近的例子来说明我这么做比较合理,但是我也不知道其中的原因(不知其所以然),
也找不到使劲的地方,后来无意中看到了分类学理论的一篇文章,
里面说到了划分标准。然后,忽然想起学习离散数学时候的集合论里面的等价关系,
说的也是这码子事,才开始了这方面的进一步思考。
然后按照这样的方式去解释我遇到的问题,果然很好使,
它让我知道我所做的事情有了依据.
就像你不知道电器怎么造的,你也可以使用,但是使用时候不免有些担心,会不会弄坏了.
如果你知道它们是怎么造的,那你就没有那些忧虑了.
===================================================
再退一步说,一个类究竟要怎么设计,毕竟还是看应用场合的具体需要。
===================================================
这个观点我赞同,隐含道家思想,
感性一点地说是因势制宜。理性一点的说是由于模型的 价值评价系数,资源数量,
约束条件的增减,自变量的增减,系数矩阵的值得变化,
,我是以线性规划为模型的,目前它能解决我的很多问题,
这里说的是其中的灵敏度分析.
现实中即使同一个模型下也没有绝对最优的的解,
最优解是随着条件的变化而变化的。也不是立刻就变的,
而是由量变到质变,灵敏度分析告诉我们如何去把握其中的变化。
===================================================
“设计一个可被继承的类”是一件很简单的事吗?
===================================================
不简单,一个独立的类好设计,但是这样的类没有意义,离开类体系.
它什么也不是.Top
22 楼FreeFice(庄鱼)回复于 2006-08-11 10:43:37 得分 0
也谈谈分类,星辰在谈论矩形与正方形在分类继承上的关系时,认为正方形可以继承于矩形,在这里我认为应该谨慎处理。
原因很简单,我们建模时通常直接来至于数学概念,但是在这个问题上,正方形与矩形对计算机来说应该是平行的,它们如果同时继承于形状或四边形、平行四边形都是一种粗糙的继承划分,为后续形状间的演变设定了过多的障碍。
狐狸发sjjf的症结在于矩形与正方形的互换,或者三角形与等边三角形的互换行为,当我们要面临这样一种存在相互演化的概念时,就有必要考虑增加中间基类,将矩形与正方形作为其平行的两个子类,同时将差异性作为类型转化要素,这样问题就变得简单了。
比如说,我们建立这样一个类型:对角线平分且等长的四边形,其两个子类分别是临边相等的正方形与不等的矩形,这样,仅需通过一个类型转换函数就可以方便的实现对矩形或正方形的判断。而且也做到了矩形永远与正方形的不同。同样,对三角形也可以作相似的划分,也就是说正三角形仅有一个点及中心描述,等腰三角形有中心及一个点角描述……,将正三角形、等腰三角形、斜等腰三角形、直角三角形……变成数据非互溶子集,可以通过一个统一的类型判定函数划分,虽然正三角形与等腰三角形无关不符合数学常识,但却符合计算机分类要求,因此,强制性的要求计算机遵行认识常识实际上是许多C++新手常犯的一种认知错误。
计算机处理数据仅有规则定义的区别,而无认知的区别,因此,定义类型及其派生类型必须以计算机的规则定义来实现,而不能以人的认识来分类,就像张三继承自人,李四也继承自人,但人是什么,人是什么也不是的抽象概念,是个抽象类,没有自己的实现方法,你非要张三是李四就是人为认知的缺陷。Top
23 楼sjjf(水晶剑锋)回复于 2006-08-11 17:32:38 得分 0
to FreeFice(庄鱼)
认真地读了你的回复,
有一点,我们的认识是相同的。
我们做的划分的概念并不等同于现实中的概念。
而且基本上举的例子都是现实中的例子概念过宽。
映射到我们的类体系中的同名概念,都去掉了些特征。
你提出的
==============================
就有必要考虑增加中间基类,.........
对角线平分且等长的四边形,其两个子类分别是临边相等的正方形与不等的矩形,
==============================
这种描述更适合数学。
但是作为设计者,我们的关注是过程中, 中间的基类它是怎么出来的?
你怎么会想到这个概念?
(不许说数学课本里面就是这么说的,那是小学生的答案)
在我的回复中,曾抄袭了几种方法。
========================================
而且得到分类的体系的方法有几种
一种是纯自顶向下的。
一种是纯自底向上的。
一种是混合的,上下求索。
========================================
我想你的这个概念的来源也和我一样是用第三种方法。
先由矩形和正方形抽象出一个比较高的概念--四边形。
然后在四边形的概念下,抽取正方形和矩形的共性,才出现夹层。
但是,如果我不要夹层,我也可以认为其他的四边形归类到一个叫 “对角线不平分或不等长的四边形”的类中。
减少了一个类层次,但如果它能满足现实需要,也能行之有效,看现实的需求而定。
不知道你有没有注意到,在你认为自己已经区分清楚了 矩形和正方形时候,
实际上涉及到两个过程,自底向上和自顶向下。
因为你的回复中没有涉及的到 和 “对角线平分且等长的四边形“这个概念并列的概念,
所以我猜想你是先自底向上抽取共性的,在得到“对角线平分且等长的四边形”这个概念后,
问题来了,你怎么知道 “对角线平分且等长的四边形” 这个概念是否合适?会不会存在另外一个下位概念,他和矩形或者正方形并列。
如果要你的类体系严谨,那么你需要回答这个问题。
这时候需要一个 自顶向下 的过程。找出等价关系才能确定在 “对角线平分且等长的四边形”这个概念在 “临边相等”这个等价关系下
只有两个等价类:矩形(这里的矩形概念被缩小了,不包含正方形,或者你看作非正方形的矩形更合适)和正方形。
这就像证明充分必要条件一样,包含充分和必要两部分。
这个例子很简单,可能根据经验一眼就能够做出这样的划分体系,但是如果是处理复杂的问题,或者你不熟悉的领域,
就需要一个方法论来做这件事情了。
我们的现实中的概念过宽,比如正方形是矩形,这是另一种划分,实际上这时候,矩形是一种抽象概念,
它是描述 正方形和非正方形的"矩形"的共性 等同于这个“对角线平分且等长的四边形“概念。
========================================
而不能以人的认识来分类,就像张三继承自人,李四也继承自人,但人是什么,人是什么也不是的抽象概念,是个抽象类
========================================
不赞同后面的观点。人是一个抽象的概念,但不是什么也不是,它是从客体张三,李四等里面抽象出来的概念。
或者说人是由地球上所有的像我们一样的客体的共同特性的集合。
在oo里面,类本身就是描述抽象概念的,对象才是客体,抽象类是描述更为抽象的概念的。Top
24 楼FreeFice(庄鱼)回复于 2006-08-11 19:41:52 得分 0
To:sjjf(水晶剑锋)
程序的设计,是以计算机的思维来进行的(请允许我这么说,虽然这是人的思维),因此我们在划分对象与实体的时候,有必要考虑清楚:什么是当为,什么是不当为。
我们习惯性的做法,是喜欢建立层的概念,每一级都是可见的可实现实体,然而,这其实并不符合计算机自己的逻辑,它喜欢对象是最终点的实例,而中间的层仅仅是概念,因此,通过概念层相互关联以实现共性的方法与实际操作,用类的比方来说,基类、派生基类都该是抽象类,而最终实现的派生类才是实的,这样可以解决并行子类之间的交互,同时避免将此子类说成彼子类。然而,这样做并不符合人的习惯思维模式,一个有经验的设计者,他的目的就是针对不同的应用情况,选择合适的方法,在两种不同的模式之间寻找一种平衡,这也是C++程序员为什么比其它语言辛苦难做的原因。
人实际上就是一个抽象概念,如果没有实际的特例描述,是无法生成一个人这个实体的,我们的大脑在我们以为概念细分以前,就已经为我们抽象出来了,然而,计算机却不会,因此有必要告诉它是抽象的,否则,它可能就真的会将张三身上的事说成是李四身上的,因为它不会将张三作为一个类,李四作为另一个类来处理,然而这点,我们人类即便是个小孩也都清楚两者的不同。
现在的问题在这里,如果完全按计算机的要求去分割类型,那么工作量将极为巨大,作为一个具体的应用来说,是否值得,这也是考量一个优秀C++设计人员的“偷懒”程度。
作为OO来说,很多人都以为OO就是针对对象类,因此会出现凡事必class的情况,其实这种观念,我认为是值得商榷的,因为对计算机来说,它的OO是很明确的实体,可以是操作控制,也可以是一段数据,甚至可以是什么都不是的空,class对它来说描述过于狭隘了。这也是我为什么很少与人谈论OO“经典”的原因。Top
25 楼steedhorse(晨星)回复于 2006-08-11 22:47:10 得分 0
我现在感觉这个问题似乎有些太抽象了,以致于我们每个人思考的角度,方式都各不相同,对楼主所提出问题本身的理解也不尽相同。:(Top
26 楼sjjf(水晶剑锋)回复于 2006-08-12 23:59:52 得分 0
to FreeFice(庄鱼)
呵呵,没太明白,愿闻其祥。
========================================================
我们习惯性的做法,是喜欢建立层的概念,每一级都是可见的可实现实体,然而,这其实并不符合计算机自己的逻辑,它喜欢对象是最终点的实例,而中间的层仅仅是概念,因此,通过概念层相互关联以实现共性的方法与实际操作,用类的比方来说,基类、派生基类都该是抽象类,而最终实现的派生类才是实的,这样可以解决并行子类之间的交互,同时避免将此子类说成彼子类。然而,这样做并不符合人的习惯思维模式,
========================================================
其实你说的不符合人的习惯思维模式的那部分。我个人倒是觉得符合人的思维模式。
随便弄个概念出来,比如人,它的定义是
========================================================================
人的生物学生命或生物的人是指属于生物分类中脊椎动物门,哺乳类、灵长目、人科,人属的有机体
========================================================================
可以看出来
动物门,哺乳类、灵长目、人科,这些都是没有实体的。
只有人属下面才有实体。其他的概念都是抽象的,都是虚的,不可能拥有实体。
这和我们oo中设计的父类如果不是抽象类的话,可以实例化的做法有些出入。
当然也不是说父类可以实例化这种方式有问题,实际上它可以更好地描述
张小三是张大三这一个事实,因而张小三有很多张大三的特点。
关于这两种方式的实质,我也没有参透。
==========================================================
它可能就真的会将张三身上的事说成是李四身上的,因为它不会将张三作为一个类,李四作为另一个类来处理,然而这点,我们人类即便是个小孩也都清楚两者的不同。
==========================================================
没有太明白这段话。而且,从张三,李四等客体上抽象出 “人“这个类,
是不会出现“把张三当作一个类,李四当作一个类“这种情况的。
而且用oo的术语来说,张三or李四只是对象,它是不会出现在类图里面的,
一般会出现在对象图,序列图和交互图等中.
Top
27 楼FreeFice(庄鱼)回复于 2006-08-13 15:12:10 得分 0
to:sjjf(水晶剑锋)
有一点,我们在认知上是不同的,那就是对人的描述,你认为人的概念是明确了的,是一个实的概念,而我恰恰认为它是一个抽象的概念。因为很简单:人这种认识是在比照张三李四一大群对象以后的一种“相似性特征描述”,而不是非此即彼的准确描述,离开“张三李四”特征概括,就无从有人的概念。至今为止,人的定义与描述都是不明确的,即缺乏一种将人直接与其它生物分隔开来的指征。一个连描述都不明确的生命体,怎么可以说是一个具体的概念类型?
人类的认识是一种跨度很大认知过程,它能够允许将抽象的与具象的概念统一起来处理,然而计算机却没有这个本事,如果计算机有了这个本事,那么机器造人就不再是想象而是事实了。
其实,我们一直是将人的个体作为单一类型处理的,这也是我们常常说个例,只是这个类里仅有一个对象而已,在一个人身上适用的东西,并不能在其他个体上适用,参照其他的个体并不能复制一个这个个体,这显然就是类属性概念而非对象概念。然而由于人的智慧太过聪敏,可以很简洁的概括抽象出一个不存在的概念来代替众多繁杂的具象描述,然后以此作为一个实征指标去分析处理,这点,计算机是做不到的,至少目前为止。
对OO来说,由于存在如此巨大的跨度,类型描述就完全依赖于应用需要,而不依赖于客观上如何描述,而这也正是C++算法设计的任务所在。Top
28 楼FreeFice(庄鱼)回复于 2006-08-13 16:12:28 得分 0
另外,从生物学上讲,“人”也并不是一个最终概念。在人科之后尚存在白种、黄种、黑种、红种等色种差异,存在蒙古、日耳曼、非裔等等血统差异,存在汉、回、满、蒙等等民族差异……。对某种族群适用的共性,在其他族群可能完全不适用,这些也都说明了人的定义存在不确定性。就算以DNA为衡量标准,那么如果两个异性在受污染的地区产下了一个DNA变异的宝宝,那个宝宝算不算人,而且如果以相似性达到某个比例以上的算是的话,其他类人生命在DNA与人的相似度达到该比例算不算是人?Top
29 楼sjjf(水晶剑锋)回复于 2006-08-13 17:05:55 得分 0
可能存在误解吧,我自始至终都认为人这个概念是抽象的。
我想要表达的意思是
自然界存在着一大堆像我一样的生物,在概念上称之为人。在这个概念下面他是直接拥有物理的存在的客体的。但是往其上的更高级别的概念如生物,灵长目等就没有直接的物理客体了,如果说有的客体的话,就是他的下位概念了,但下位概念有可能是抽象的,(抽象的东西也可以作为客体,但是跟我们的客体直观认知有点违背,但我想它是正确的,我对这点还没有找到确认的证据)。
上位概念和下位概念的区别在于类型上,而不在值上,比如我们区别张三和李四两个客体,应该是区别于他们在同一个类型上的值,而不是类型的多少,就像比较同一个类下面的实例一样。
而我们区别不同的类,比较的应该是他们的类型,
(但是,如果把类型也当作一种值处理,这些是否能够统一到一起去,就像传指针和传值一样,其后的实质是什么?)
再如你举的例子中,我们区分在“对角线平分且等长的四边形”这个概念下区分矩形和正方形
是否可以认为是针对 临变这个类型的值(相等和不相等) 来进行区分呢?
我隐隐约约感觉他们应该是一致的,具体的数学描述,以后如果有能力再整理出来。
而且认这个概念在不同的体系的概念特征是不一样的。
比如在化学和常规物理领域中水的概念是不一样的。
化学里可能关注的是分子构成 h2o,仅此可能就满足他的需求了。
常规物理可能关注 密度,温度等的方面,
而且可能所处的类体系的位置也不一样。
设计师要设计合理的类体系,就要从这现实应用出发。
================================================
其实,我们一直是将人的个体作为单一类型处理的,这也是我们常常说个例,只是这个类里仅有一个对象而已,在一个人身上适用的东西,并不能在其他个体上适用,参照其他的个体并不能复制一个这个个体,这显然就是类属性概念而非对象概念。
================================================
如果一个类仅有一个对象,而不是现实需求要求你这么做的话(比如符合sigleton模式)。
那么意味着抽象程度不够(或者可能就不应该叫抽象,仅仅是把客体信息化而已,可以认为还是对象)。
抽象出来的概念是一个共同属性的集合。
在该抽象概念下描述的对象都会拥有这些属性,但是其属性值可能不一样。
而不会有“一个人身上适用的东西,并不能在其他个体上适用“这种情况,
如果有,那么可以考虑是否抽象不当。
=========================================
人类的认识是一种跨度很大认知过程,它能够允许将抽象的与具象的概念统一起来处理,然而计算机却没有这个本事,如果计算机有了这个本事,那么机器造人就不再是想象而是事实了。
=========================================
呵呵,好像方向有些偏离了,我们现在讨论的是我们如何抽象,而不是计算机如何抽象。
人工智能领域发展很迅猛,机器自动学习已不是空中楼阁,在一本很古老的书《视觉思维》
里面就举了机器如何通过几个例子学习拱形这个概念,而且深蓝的胜利也说明了这一点。
btw:讨论oo,一般都是用uml来描述,不是用cpp.
Top
30 楼sjjf(水晶剑锋)回复于 2006-08-13 18:49:48 得分 0
================================================
对某种族群适用的共性,在其他族群可能完全不适用
================================================
这点很正常,在一个种族里面的抽象出来的共性,在其他族群完全不适用,也只是部分共性而已,
肯定有一些是可以共用的共性,如果真的什么都没有,至少还有一个"族群"这个概念可以共用。
抽象讲究的是存同,不是求异,求异是继承或者实例化时候讲究的。
这个问题,是属于类的体系问题。
一个合理的类体系是紧扣需求的。
如果要研究人的色种可以在人的概念上加入色种这种共性
(简化的假设,实际上不一定在人的概念上加,可能会在他的某个下位概念上加)。
所谓的白种、黄种、黑种、红种..不过是人这个上位概念下的一种划分而已。
这个不是说对人的定义存在不确定性,而是说,需求存在不一样,导致相应的人的定义不一样,
如果你要研究种族,那么种族这个特征也可以加入人的概念中。
这里可能会存在一个误导。认为抽象会导致加入越来越多的特征。
实际这是误解,如果你以某个类体系为原型,当你的需求更改了后,比如要关注色种,
那么这些客体(张三,李四)信息化的过程中就会无形中有了一种叫黄色,黑色之类的特性
(你刻画客体的信息变多了)。
如果你要关注色种,那么就需要根据你的要求抽象出一个叫色种的东西。
抽象是不是越抽象共性越多,而是越抽象共性越少,
用分类学的术语说就是 内涵越少 外延越多。
我见过有些刚接触oo的人做的“抽象“是:拿几个对象如A,B,C在一起做抽象,
特性集合假设如下 A(a1,ttt) B(b1,ttt),C(c1,ttt)
他们抽象出来的特性是 Z(a1,b1,c1,ttt)
这不是抽象,叫多重继承还差不多,真正的抽象应该是 Z(ttt)
这个例子似乎有点好笑,但是在现实中,却有很多人犯过类似的错误,可能是受思维定势的作用吧。
当你因使用父类接口编程没有子类的某个属性而需要在父类里面加入的时候就差不多犯了这个错误。
因为,如果这个属性(or行为)只是某一个子类特有的话,那么就不应该往父类里面加。
如果这个属性是父类下的所有子类都有的话,那么它就应该移动到父类中,
而在子类是不会重新定义的。这点点似乎没什么大不了的,但真正要命的是
所有针对这个父类(接口)的应用逻辑,也可能会因为以前的抽象不当的概念导致错误,
这概率很大。不过幸运的是,oo的方式的设计界定影响范围还是很方便的。
关于多重继承的类体系,虽然我也用过,但是我还没有研究过它,因为单重继承还没有弄明白。
关于那个变异人的故事。不知道是否是超人前传的另一个版本。
我不是学生物学的。但是也乱弹一把吧,其间的对和错不重要,只是个人的见解。
往极端一点,如果那个“变异人”(在没有弄清楚之前,或者叫做东西更合适)
如果真的变异的和我们的这个世界的狸猫没有差别的,
那么对不起,这个不是人,而是狸猫,虽然它是人生的,或者也许他还是某一个皇妃生的。
那我们为什么还称一些畸形人为人?人体内很多种基因,其中有一些是很关键的基因,
它决定了我们的人的特征。畸形只是某个细节畸形而已,
但是在整体框架下还是能看清人的特征的。表面看缺胳膊少腿的,
但是实际上,他们的关键性基因并没有变异,如果这些关键性的基因变异了,那么它也不会发育成人,或者会是别的动物(怪胎),但不是人。
(这段言论不包含对残疾人,畸形人的歧视的意思,申明先)
Top
31 楼fixopen(dup)回复于 2006-08-14 15:56:42 得分 0
我觉的似乎得首先明确一下基本概念了:
不变性:类之为类的一个先决约束,或者说先决条件。我们知道,一个类表达一个概念,一个概念之所以是自身而不是别的概念,依赖于这个概念有意一些别的概念所不具有的一些特征。比如说“人”这个概念表达的是一个不同于“桌子”的东西。
这么说似乎还有点抽象。我用一些耳熟能详的东西来说明吧。一个vector,表达一个顺序同质对象容器,其size总是等于其元素个数。我们的push_back或者pop_back,在增删元素的同时,一定会保证size等于元素个数。所有对于这个vector实施操作的动作,都必须维持这个关系,那么,我们就说,size==vector中元素的个数是vector这个类维持的一个不变性。
我始终觉得,大家的讨论似乎都受到各种oo语言的限制,由于它们很少能够直观自然的支持不变性,所以大家都觉得正方形继承自矩形会有讨论的余地,或者正整数继承自整数也不会被认可。而这对于我来说没有任何问题。
因为:继承对我来说就是特化,就是子类化,类对我来说就是表达一个概念,一个概念就是规定了一个集合,继承就是根据某种手段选取子集的过程。继承就是分类。
我们有很多维度实施分类(可能是无穷的维度),对我来说,就是按照某个属性的取值范围实施子集化手段,所以,我们需要某种程度上的多继承。
比如:
事物
红色的
绿色的
事物
可吃的
不可吃的
我想表达红色的可吃的事物,我从红色的和可吃的继承下来有问题么?我认为没有。上面,对于事物我从两个维度进行了分类,现在我想同时关注这两个维度,显然,它可以把事物分为2^2个子集,其中每个子集都是事物全集的一部分,同时,红色的可吃的,红色的不可吃的,显然是红色的这个子集的子集,同时,它们(红色的可吃的,红色的不可吃的)也分别是可吃的和不可吃的子集的子集。Top
32 楼sjjf(水晶剑锋)回复于 2006-08-14 17:26:32 得分 0
to fixopen(dup)
我不知道 不变性这个概念合不合理,(请原谅,关于cpp的书,我读的不多,好像都没有提到类的 不变性 这个概念)
依据你的描述,你说的不变性应当是区别特征。 一个概念虽然是很多特性(特征)的集合。
但是其中可能只有一些特征才是能够把它和别的特征区分开来,这些特征或者特征的组合就叫做区别特征。 对于不同的类体系,即使是同名,大致同位置的概念,其区别特征也可能会不一样
(我倒没有对这个犯过迷糊,好像一般情况下都能区别出来,所以也没有思考它的实质)。
你举的例子中
事物
红色的
绿色的
事物
可吃的
不可吃的
你想表达"红色的可吃的事物"
实际上不知道你是否会注意到 你的概念的中的事物实际上有两个类型: 事物(颜色,动作)
对此,如果你用另外一种纬度划分,你会得到四个子集
{红色可吃,红色不可吃,绿色可吃,绿色不可吃}
我想这也应该满足你的要求,也不失为一种方案,
因为我以前的公司尝试oo从我开始,所以这也是我的应付对策,幸运的是,它能够把复杂的需求描述清楚,并条理化,当然,我离开的时候,它也有一个实现的可以运行的版本了,那段时间我拼命的找数学依据,就是要证明我这么做是对的,可行的,因为我心里也没有底。
但是这种方案适合于你做一个干净的设计的时候采用。
如果你在别人的类体系基础上做设计或者重构的话,
(实际上很多时候都是这样的,你不可能重新造轮子)
那么问题就来了。
刚才提的那个模型不适合揭示问题(可能会引起误解),不妨把这个模型推的更抽象一点。
事物(thing)
按照第一纬度划分
第一子集 a1
第二子集 a2
按照第二纬度划分
第一子集 b1
第二子集 b2
实际上,a1是thing的特化,thing是上位概念,它拥有的特征是最少的。
a1可能会拥有thing中没有的特征。a2,b1,b2同理。
如果你现在想表达诸如红色可吃的概念,你可能会用多重继承,继承a1,b1但是
这种继承的合理性的不到保证,因为可能a1中的其他特征可能会和b1的其他特征矛盾。
(这种情况我在修改类体系结构的时候,碰到过,不过当时没有时间做太多的思考)
当然,如果没有矛盾,应该是可以多重继承的。
(这仅是同一层次的多重继承,不同层次的呢?它们的合理性是如何判定的?
有什么依据和理由?)
实际上,现实中有很多多重继承的例子,比如一个人可以拥有身份,比如教师,父亲....
这样子是合理的,另外一类,比如(人马)这种怪异的继承,我想应该是不合理,否则它就不应该
只存在于神话中了,(但也说不定,以后科技发达了,也许会有。)
这一段只是我的直观经验,我不能保证它的正确性,我也在思考中。Top
33 楼FreeFice(庄鱼)回复于 2006-08-14 20:44:08 得分 0
To:sjjf(水晶剑锋)
有关人的定义及类型描述,你其实已经不知不觉地站在了我这边,而仅仅是不愿承认人这个类型应该是抽象的,因为继承也好派生也好都是指子类而言,由于人的思维灵活性,可以直接跳跃抽象与具象之间的鸿沟,然而计算机则不会。
人的思维分类一直也是以值变化临界点来划分世界的,即便是我们对化学的成分的认识也是如此,就拿H2O来说,如果多了一个H+离子,则成为强酸液,而少一个H+离子则成强碱液,O-富余到一定的量后会反应生成H2O2,少到一定程度后会电离出H2,而这些成分上的变化恰恰是以元素成分比例来决定的。即便是高分子聚合物,化学分子结构式多么的复杂不同,其实也都是因为元素微粒间的键值及角度区分的,我们引以为傲所有定性认知都是依赖于数值变化临界点来划分的,定性的事物最终都可以通过定量的数值加以表示,区分类型的最佳方式并不是所谓的“定性”,恰恰是对定量的分析与发掘。这也是我对UML描述类型觉得不够完善的地方(UML依然是基于“定性”概念,缺乏“定量”类型分割设计模式,对OO走向OI(Object Intellectualized)际上设置了障碍)。C++虽然不够合适,但在数据集成上,至少允许我加入定量设置类型的方法,UML实际上依然是基于层的概念,这与我们今天所说的这些跨越层级设计思想,依然是存在差距的。Top
34 楼sjjf(水晶剑锋)回复于 2006-08-14 22:29:07 得分 0
============================================================
有关人的定义及类型描述,你其实已经不知不觉地站在了我这边,而仅仅是不愿承认人这个类型应该是抽象的.
============================================================
我不知道这句话从何而来?
我翻了一下我的发言,从开始到现在,我都没有说过人这个概念不是抽象的,
从我的分析过程里面,你也应该能够看出来的,
开始我以为你是误解了,澄清了一下,但现在还在坚持这个观点,让我有些郁闷。
---------------------------------------------------- 引用开始
================================================ 你的回复开始
其实,我们一直是将人的个体作为单一类型处理的,这也是我们常常说个例,只是这个类里仅有一个对象而已,在一个人身上适用的东西,并不能在其他个体上适用,参照其他

