`
calmness
  • 浏览: 350727 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类
最新评论

OO—现实与实现的分歧

阅读更多
   最近在和朋友做一个小的系统,对系统进行设计时与朋友的理念有所冲突,于是乎就想起了一个老问题,那就是正方形与长方形的继承问题。
   
OO可以说是现实世界在计算机世界的一个映射,而对于正/长方形,实际上是对正/长方形数学定义在计算机的一个映射的问题。

首先我们来看看在现实中,长方形的定义:
有一个直角的平行四边形是长方形。

再来看看判定定理:
定理1:有三个角是直角的四边形是长方形。
定理2:对角线相等的平行四边形是长方形。

以上就是长方形在现实中的定义以及判定定理。以此来看,正方形完全符合以上定义以及判定定理,所以可以得出正方形就是长方形,是它的一种特例。

在阎宏博士所学的《java与模式》一书里的观点是反对正方形是长方形的子类的,同时他写了一个例子出来:
  public void resize(Rectangle r){
        while(r.getHeight()<r.getWidth()){
           r.setWidth(r.getWidth()+1);
        }
    }


这个例子是长方形的一个方法,用来不断增加长方形宽度,当宽度超过长度就停止增长,当传入对象是正方形的时候,这个方法就无用武之地(修改)。对于这一点,我的反驳很简单,是谁规定了长方形的边长必然是一个长一个宽呢?在现实的定义和判定定理中,并没有这一条吧。我记得在以前读书的时候,就有过一道判断题:长方形的长一定比宽的长度长。这道题目的答案就是错的。而在这里,阎宏博士通过一个自己定义实现的方法来扭曲现实中的定义,这一点已经明显违反了OO设计的根本,那就是客观的反映现实世界。

以上说了那么多,实际上我想说的是,在进行对象设计的时候,我们要把握好一点,那就是客观的反映现实的世界,当然要做到非常准确是很难,至少在现实对象有明确定义之时,我们不应该主观的加上自己的定义实现,让实现与现实产生分歧。
分享到:
评论
32 楼 xly_971223 2007-04-19  
没有文字也能提交上来? 表单里好像有长度限制吧
31 楼 gstripe 2007-04-19  
不好意思,网络太卡,刷了两下居然上面两条没有文字。晕死
30 楼 gstripe 2007-04-19  
平面几何图形
           平行四边形
                     矩形
                         长方形 正方形
29 楼 firebody 2007-03-12  
age0 写道
楼上几位又扯远了,“在恰当的地方恰当的使用OO”,这种没有营养的废话不说也罢。

何时、何地以及如何实现OO才是需要反复讨论的课题。


如何设计是非常主观的事情,在论坛里面,针对一个模糊的设计来讨论“如何设计”是非常“浪费生命“的事情。 

28 楼 age0 2007-03-12  
楼上几位又扯远了,“在恰当的地方恰当的使用OO”,这种没有营养的废话不说也罢。

何时、何地以及如何实现OO才是需要反复讨论的课题。
27 楼 抛出异常的爱 2007-03-12  
现实世界如果真的那么容易就可以变成对象
那要我们何用?
对象只是假装自己是现实世界中的一员
大象用程序的方式模拟现实而已
如果不能模拟那么一定是你的程序错
而不是现实有错....
26 楼 firebody 2007-03-12  
simohayha 写道
对于复杂的处理逻辑,计算逻辑复杂的系统时可能FP会更好些,这时候面向对象就显得不合时宜了。


“对象”是达成“实现需求”得一个手段,如果不用对象的设计,直接用过程式的方法能够获得“更清晰,更简洁”的代码,那就完全可以摈弃 “对象设计”,当然,如果在复杂一点的需求中,前面的“假设”我还很少看到。
25 楼 simohayha 2007-03-12  
对于复杂的处理逻辑,计算逻辑复杂的系统时可能FP会更好些,这时候面向对象就显得不合时宜了。

面向对象很好,是不错,可是你硬要用它来解释一切东西,那就不对了.
24 楼 firebody 2007-03-12  
age0 写道
人、女人、男人、老人、年轻人,都是现实中存在的实体对象。

它们之间存在任何继承关系吗?如果存在,应该如何设计呢?

属性及行为如何影响我们的设计?

最后,当我们陷于矛盾及困扰的时候,是不是从一开始我们就已经错了呢?


恩,或许在真的项目里面果真如此。

讨论如何设计对象以及他们之间的关系,如果这个讨论发生在讲解“设计模式”的时候,还算“值得”讨论。

如果在项目里面,这个讨论如果 “过于详细(或者细节)”就显得过于“先于需求”了。

可以想象怎么实现用户的需求的时候 ,脑子的思维是多么活跃:设计一个人,一个长方形,再来一个很好的继承关系,再通过组合,这样就可以。。。。。嗯,这里还多一些抽象,以免........(省略100000字)

这里我不得不佩服人的脑子的想象力,以及在各种技能条件下的充分发挥。
当然,对于这样充分想象的工作者,说明他是有相当的能力,因为很多一些人连合理的想象的能力都达不到,当然,不能磨灭他们将来可以达到的可能性。

这里,我不得不打击那位 充满想象力的“对象设计者”一下,其实他几乎99%的想象都是无用的,甚至可能使以后系统实现时的“累赘”和“缺陷来源”。过于“执着”自己的设计而不遵循“需求需要”的原则,这样的教训更来得惨重。

粗略的类图在需求开始分析阶段,是有必要的。但是没必要如此详细。 特别是涉及到“继承”/各种设计模式的使用的时候。 这些更细节的东西 最好能够通过需求推导出来。

当然,不是每个人都能把握在 coding过程中,把握重构的细节,甚至把握“重构出更合理的对象关系”的能力。然而,如果能够这样做的,项目的质量总归比要“先于需求实现”的质量总归要来得高得多。 部能够这样做的,就成为“攻击敏捷开发”的原因之一。





23 楼 age0 2007-03-12  
人、女人、男人、老人、年轻人,都是现实中存在的实体对象。

它们之间存在任何继承关系吗?如果存在,应该如何设计呢?

属性及行为如何影响我们的设计?

最后,当我们陷于矛盾及困扰的时候,是不是从一开始我们就已经错了呢?
22 楼 yiding_he 2007-03-10  
将正方形当成长方形来用,可能会造成不可理解的结果。但是仔细追究,正方形的面积计算实际上是一种简化的方法,其本意还是“长”乘以“宽”。如果一定要我写一个继承于长方形的正方形的话,我会在 setHeight() 方法里面写上 throw MethodNotImplementedException();
21 楼 wkxxkw 2007-03-05  
8错,LSP一章中提到过这个问题,他说  IS-A 是关于行为的,意思很明显:如果行为不同,就不赞成设计成为继承。我觉得应当抽取公共部分,设计为接口
20 楼 xly_971223 2007-03-05  
taya 写道
关键要看调用者的上下文,看其对行为方式的预期
在上下文中正方形和长方形的行为方式相同的才能继承,不同的话就不能

Bob大叔在《敏捷软件开发》的LSP一章中提到过这个问题


我觉得根据正方形和长方形的行为方式可以分为两种情况考虑:
1.行为方式相同时:将正方形看作是长方形的特例,也就是说我设计的时候不考虑正方形这个类,要构造一个正方形需要通过构造一个长宽相等的长方形来实现。
2.行为方式不同时:长方形 正方形继承同一个接口Shape,各自实现自己的行为

另外是否可以考虑把Rectangle等设计成不变模式(Immutable Pattern),这样就不需要考虑由于对象长宽变换而导致的形状的变化

另外2:对于正方形继承长方形这种方式有点牵强
19 楼 抛出异常的爱 2007-03-05  
二年前就有人在这个论坛讨论过的问题

观点一
长方型不是正方型的父类
两个的基本属性不同
一个是长宽,另一个是边长

观点二
长方型可以长宽不等
那么正方型就是长宽相等

所以型状的改变就不是单独改变长宽
而是两个一起改变
如果方型,改变成不同时抛出异常

观点三
方型重写
改变长宽的方法
让每次改变是将长宽同时改变

观点不同建模也不同

18 楼 silentlakeside 2007-03-05  
我觉得是对现实的模型理解有误,现实中并没有长方形/正方形这种物体,长方形/正方形只是物体的一个外观,当物体改变长度/宽度以后,其形状会发生变化,因此不存在正方形改变长度/宽度会变成非正方形,只存在物体改变了长度/宽度,从而使得形状从正方形变成了非正方形。

当然纯粹从几何学的角度可以另外讨论。
17 楼 taya 2007-03-05  
关键要看调用者的上下文,看其对行为方式的预期
在上下文中正方形和长方形的行为方式相同的才能继承,不同的话就不能

Bob大叔在《敏捷软件开发》的LSP一章中提到过这个问题
16 楼 clamp 2007-03-04  
1、正方形是可以继承长方形的(但这是有前提的,仅继承直角平行四边形)
   事实上正方形还可以继承菱形(仅继承边长相等这个概念)
2、长方形的长和宽这两个属性及其相关方法不应该被正方形继承
  



15 楼 gigix 2007-03-04  
Julien 写道
public void t(Rectangle r){
    r.setLength(5);
    r.setWidth(4);
    assertEquals(20, r.getArea());
}

正方形应该在setter里面保证长宽相等
或者在不相等的时候throw Exception
setLength的时候长宽都为5
setWidth的时候长宽都为4
然后assertEquals的时候应该是失败,20VS16

那么使用这些类的程序应该怎么写?是不是先判断一下类型?
说来说去,又回到正方形不能继承长方形了。
14 楼 Julien 2007-03-04  
public void t(Rectangle r){
    r.setLength(5);
    r.setWidth(4);
    assertEquals(20, r.getArea());
}

正方形应该在setter里面保证长宽相等
或者在不相等的时候throw Exception
setLength的时候长宽都为5
setWidth的时候长宽都为4
然后assertEquals的时候应该是失败,20VS16
13 楼 fyun 2007-03-04  
magic_seek 写道
正常情况下正方形是矩形的特例,所以正方形是矩形的子类,因为是特例所以多了很多约束,所以很多方法是需要覆盖父类的。


11楼是正解啊。

这里不是什么覆盖父类的问题,考虑这样的代码

public void t(Rectangle r){
    r.setLength(5);
    r.setWidth(4);
    assertEquals(20, r.getArea());
}


分别传入长方形和正方形的实例,分别是什么结果?

相关推荐

Global site tag (gtag.js) - Google Analytics