正方形继承长方形违反liskov原则?

zmm048 2007-09-05 08:36:48
几乎所有的将Liskov原则的文章都提到了“正方形继承长方形违反Liskov原则”。
但都说的不清不楚的
假设我有如下的两个类,请问哪个地方违反了Liskov原则呢?


public class Rectangle ...{
protected double width;
protected double height;

public double getWidth() ...{
return width;
}

public void setWidth(double width) ...{
this.width = width;
}

public double getHeight() ...{
return height;
}

public void setHeight(double height) ...{
this.height = height;
}

public double calcSize() ...{
return this.height * this.width;
}
}



public class Square extends Rectangle ...{
@Override
public void setHeight(double height) ...{
setEdge(height);
}

@Override
public void setWidth(double width) ...{
setEdge(width);
}

@Override
public double getHeight() ...{
return getEdge();
}

@Override
public double getWidth() ...{
return getEdge();
}

public double getEdge() ...{
return this.height;
}

public void setEdge(double edge) ...{
this.height = edge;
this.width = edge;
}
}
...全文
612 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
bushuang 2007-09-06
  • 打赏
  • 举报
回复
讨论这个话题有什么意义呢....
lfcai 2007-09-06
  • 打赏
  • 举报
回复
学习下~~~~~~~
谢谢上面的同志们
zmm048 2007-09-06
  • 打赏
  • 举报
回复
那么 子类是父类的某种特例,这种情况下是否不应该使用继承呢?因为特例必然是在父类的基础上添加了约束的

回复人:cxz7531(大花猫) ( 五级(中级)) 信誉:97 2007-09-06 09:02:22 得分:0
关键是子类扩展父类的时候,只能增加字段和方法,而不能增加约束。
长和宽必须相等是对父类中两个字段的约束,而在子类无法扩展这种约束,这算是目前oo语言的 局限性。期待下一代oo语言解决。

cxz7531 2007-09-06
  • 打赏
  • 举报
回复
关键是子类扩展父类的时候,只能增加字段和方法,而不能增加约束。

长和宽必须相等是对父类中两个字段的约束,而在子类无法扩展这种约束,这算是目前oo语言的局限性。期待下一代oo语言解决。
zmm048 2007-09-06
  • 打赏
  • 举报
回复
是否可以这样认为
Barbara Liskov 提出了LSP原则,
Robert C. Martin强化了这一原则
Robert C.Martin的LSP强化版提出了更苛刻的要求,即要求子类不能改变父类的行为,因此也提供了更好的扩展性
  • 打赏
  • 举报
回复
接楼上楼上

原则只是界定了一个规范,让我们可以看到一个好的系统应该如何去实现的,而且这些原则都是一些前辈经验的总结,我们应该汲取他们的经验的,在软件设计时我认为很有必要考虑一下的。
zmm048 2007-09-06
  • 打赏
  • 举报
回复
接楼上
不应该刻意地去想这个原则, 那个原则

并不意味着我们不应当准确的理解这些原则
jk88811 2007-09-06
  • 打赏
  • 举报
回复
接楼上

不过好像我们在设计的时候, 不应该刻意地去想这个原则, 那个原则...

原则仅仅是原则, 用来指导我们, 而不是左右我们...
  • 打赏
  • 举报
回复
我认为有意义的,里氏替换原则是面向对象设计原则中五大原则之一。

要设计比较好的应用,至少要符合这些原则的。
timerri 2007-09-06
  • 打赏
  • 举报
回复
对于实践而言,毫无意义
  • 打赏
  • 举报
回复
“能够施行于base class对象上的每件事情,也可以施行于derived class对象身上”
____________________________________________________________________________

这个就是“里氏替换原则”。
shili150 2007-09-05
  • 打赏
  • 举报
回复
这些我不是很清楚
但也up一下
Squall1009 2007-09-05
  • 打赏
  • 举报
回复
不知道什么叫“liskov原则”,但

《effective C++ 第三版》里面讨论过这个问题 可以参考p154-p155
其大致的解释为:
一些可以运用在矩形上的方法(比如单独增加矩形的长或者宽)却不能运用在正方形上(因为正方形必须长和宽一致)。
简单的说:
“能够施行于base class对象上的每件事情,也可以施行于derived class对象身上”
  • 打赏
  • 举报
回复
这样看来好像是 Robert C.Martin 曲解了里氏替换原则的本意。
zmm048 2007-09-05
  • 打赏
  • 举报
回复
我觉着Robert C. Martin对liskov的简化改变了Barbara Liskov的本意呀
Liskov的意思是
对于任何子类对象,都有一个父类对象,是的使用此父类对象的程序该为子类对象後行为不变。
但是Robert C.Martin的意思变成了:
对于任何父类对象,都有一个子类对象,是的使用此父类对象的程序该为子类对象後行为不变。

Liskov Substitution Principle:
What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T." - BarbaraLiskov, Data Abstraction and Hierarchy, SIGPLAN Notices, 23,5 (May, 1988).

以下是Robert C. Martin的简化版:
Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it - Robert C. Martin, Engineering Notebook, C++ Report, Nov-Dec, 1996

Subtypes must be substitutable for their base types - Robert C. Martin, Agile Software Development Principles Patterns and Practices,2002


feihua317 2007-09-05
  • 打赏
  • 举报
回复
我觉得根本没违反啊!长方形的长和宽相等不就是正方形吗?正方形是长方形的特例,完全可以继承。
iboy1983 2007-09-05
  • 打赏
  • 举报
回复
感觉Martin这人就会把屁话说来说去。目前搞面向对象的所谓大师都是Java发家的,好点的就算对更早期的和复杂的面向对象语言也很熟,可以这么说,他们的局限性是因为他们是程序员起家的。计算机科学的根本在于各种数学上的抽象,而我怀疑象Martin这类人,连与计算机学科关系十分密切的如《算法论》之类都没有好好看过,说白了其真实水平比你我高不到哪里去(当然我也没好好看过)。

你说的这个长方形和正方形的例子,继承之时相当于重新定义了语义(其实还可以从很多个更根本的角度来看),这样表面文字上来看是继承,其实根本不是真正的继承关系,自然会产生问题。再从测试来看,这个测试只覆盖了特殊情况,既然这个对象对于测试来说属于黑盒(里面如何变化外部不清楚),那么这个测试本应定义成测试结果是不是等于W乘以H,以求证Area与W和H的关系是前者等于后两者相乘,而并非一个固定用例的测试,而这个测试显然没有做到这一点(因为它的用值并非来自于赋值后重新取出的W和H),所以出错也是自然而然的事。因为它用的并非这些本来都是很自然的事,想不清楚只是经验不够,思维上还没有统一起来形成可以覆盖的高度。

现在让这些大师们一顿云山雾罩,事情反而变得玄妙和复杂了,真是SHIT。以上言论不是针对LZ,而是针对绝大多数靠Java的炒作而出书立传发家的大师和专家。

=======================================================================
这是网上高手给出的解答
zmm048 2007-09-05
  • 打赏
  • 举报
回复
每构造一个边长为X的正方形,就可以构造一个长、宽都为X的长方形,使得任何使用这个长方形的地方替换成正方形後,不改变程序的逻辑,因此,正方形继承长方形是符合Barbara Liskov对里氏替换原则的。

但是并不是任何一个长方形,都可以找到一个正方形,使得任何使用这个长方形的地方替换成正方形後,不改变程序的逻辑
因此,正方形继承长方形是不符合Robert C. Martin对里氏替换原则的。

所以 觉着Robert C.Martin 曲解了里氏替换原则的本意

62,616

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧