谢谢BanQ大哥!请多指教啊!
刚来Jdon,看到了中国Java的希望!

http://www.jdon.com/jivejdon/thread/32771.html

我认为不要过于的执着于约束上面

你非要说oo思想就必须映射或者基本映射世间父子继承关系的所有映射,这本身就不合理不是么?

颗粒度不能过细,过细只会浪费资源啊。解决问题才是问题的关键。

正方形长方形的讨论是阎宏的书里的吧?我也记不清了。

他是说,大家都认为正方形是长方形的特例,那么就应该可以定义正方形继承长方形。作为长方形,有长和宽两个属性,而正方形有边长这一个属性。所以对于正方形来说,当边长、长、宽任何一个属性被修改时,都会把它们置成相同的值。

如果有个人写了段给长方形变形的代码,传入参数是一个长方形,先比较长和宽,如果长和宽相等或者长比宽小,就把长增一,然后循环再比较,直到长比宽大才停止。

这里出现一个问题,如果传进一个长方形,代码正常执行;如果传进一个正方形,则会是死循环,从而破坏了里氏替换原则。而里氏原则是不能被破坏的,由此只能得出结论,正方形不能继承长方形。

我觉得是阎宏瞎说八道,显然他没考虑清楚。只能说在他目前设计的长方形类下,正方形不能继承长方形。按他的这个设计,应该给长方形增加一个boolean属性, 指示当前类是否具有正方形的特征。从另一角度,也可以说,他的这个抽象并不代表长方形的本质,势必在应用中造成一定的问题。

用不到的东西就不用管?貌似记得某本书上说过这很危险。。。

阎宏的确是在瞎说八道,
死循环为什么就破坏了里氏替换原则???这个有定义吗?
死循环是它程序的bug,他举得例子是bug,他企图用bug来否认逻辑?


正方形能用他写的这个resize方法吗?不能,这是个bug,他显然没有考虑正方形这个特例。
再说清楚些,人能走路大家都承认吧,没腿的残疾人能走路吗?你能说残疾人不是人?只能说人这个类,走路这个方法写的有bug,没有考虑残疾人的情况。或者说走路这个方法/有没有腿 根本不是人的本质特征
[该贴被accipiter于2007-11-19 16:01修改过]
[该贴被accipiter于2008-04-24 10:20修改过]

在网上搜索关键字“长方形 正方形 子类”,就找到了这里。

我也感觉阎宏有点瞎扯,为啥偏给正方形加上一个side属性?

正方形是矩形的一个特例罢了,只不过width和length相等。
难道矩形的长和宽相等时,它就不是矩形了?这是什么?所谓的量变引起质变?

所以正方形根本是不存在的一个类别,只能说它是矩形的某种情况。

就像前面某朋友说的,60的妇女是女人的某种特殊情况,难道60的妇女就不是女人了?偏要分出年龄等于60这样的一个类出来?

还有那椭圆和圆也一样,圆是椭圆的一个特例而已。

1、正方形和长方形的例子不是阎博士的,是bob大叔介绍LSP的例子。
2、Is a关系的本质问题的研究,导致了<design by contract>契约式设计的出现,在Eiffel中被支持。Meyer的咚咚。
3、模拟不可能绝对映射,

翻翻旧帖呵呵……随便说两句:

1.约束的问题:目前的OO语言和建模中确实没有很清楚明确地处理这个问题。面向契约的编程也并没有发展成什么样子。如果要我对约束是什么建模:我认为,约束是类的内部属性,同时它是特殊的aspect,它的所有结合点都在类内部(进行各种check)。每个类除了属性,功能,还要有一系列内部的aspects才算完整。继承的时候子类也应该继承这个aspect。当然它还要支持各种逻辑操作。……基于这个理念,或许我们能够更加OO地建模。或许能在java上整出一套框架?哈哈

2.那个给正方形resize的外部方法问题,应该是阎宏同学脑残了。

3.关于女人是不是一定能生育,我觉得如果你要抠非得20-50岁的女人才能生育,那最好再继承出“育龄女人”这样的东西。
[该贴被sleepinglord于2008-06-06 11:12修改过]

分清这种继承是几何学上的概念还是在领域里的概念。如果不能符合领域意义,也就无所谓继承不继承了。
管理员是从民众继承来的,他不只负责管理,也要负责普通民众的社会交际,但是对于某一个企业的管理员账号,可能就是名副其实的“管理员”,他就负责管理,别的什么都不管。
同样是管理员,在不同的领域里就有不同的意义和从属。

其它的一些东西:UML有些表述在语言级别体现不良,比如关联、聚合、组合,体现在语言上就不是那么一回事了。
真能在语言层次上做到聚合必须通过聚合根访问,可能效果能好点。

没错,死循环就是他bug.谁规定长方形边长不能相等了。明明是自己考虑不周,还说不能继承啊。这么说就没有能继承的了。任何一个继承,我都能做出来反例,你只要找出子类特殊化父类地方,肯定能写出类似代码。

《敏捷软件开发-原则模式与实践》中不是在讨论开-闭原则的时候讨论了这个问题,而是在Liskov替换原则一章讨论了这个问题。
这一章对这一问题的讨论是很深刻的,抽丝剥茧,有理有据。由于这种继承违反了lSP,造成的运行时动态产生的错误,在测试和纠错方面都有严重的困难。

这个问题和《Header First 设计模式》的那个鸭子的例子是共通的,也许读了那个例子,会少些争论。

正方形继承矩形类的做法无疑是错误的:
对于那个变形方法来说,他获得的对象是矩形,因为矩形的行为中定义了长宽可以分别做任意修改而不会互相影响。用一个类继承矩形没有错,错就错在这个类修改了父类的这种行为。
其实从开闭原则更容易看待这个问题。分别设置高和宽是矩形类的public方法,这两个方法是“开”的。在正方形类继承他的时候,他可以重写这两个方法,没有问题,但在方法的实现上实质是正方形类“闭”了一个方法,简单的来说就是正方形类想“private”setWidth()或setHeight()。子类绝对是不能“闭”父类“开”属性的。
由此引申继承的问题,extends关键字代表“扩展”,即子类应该是扩展了父类的行为和属性,而不应该是加入了更多的约束。即子类应该比父类更“开”,而不可能是更“闭”。
PS:“正方形是一个矩形”这句话其实没说完,完整的表达是这样的“正方形是矩形的一个特例”。从这里可以看出来,正方形只是矩形这个类的一个实例,创造这个实例的人应该自己管理他对这个实例的约束。而如果你要从这种带有约束性质的实例来抽象出一个类,那么这个类绝对不可以从这些实例的类中继承。
再说简单点:在一个矩形对象恰好在宽、高相等的时候,我们才从概念上认为它是“正方形”。