长方形有二个属性长和宽。并有一个设置长的方法和设置宽的方法,还有一个求面积的方法. 
像下面 
private int length; 
private int width; 
public void setLength(int lenght) { 
this.length = lenght; 

public void setWidth(int width) { 
this.width= width; 

public int getArea() { 
return this.length * this.width; 

如果说正方形是长方形的子类。为了保证正方形长和宽相等,那对应于正方形的二设置长宽的个方法就得改成 
public void setLength(int lenght) { 
this.length = lenght; 
this.width= lenght; 

public void setWidth(int width) { 
this.length = width; 
this.width= width; 

那我们想想用户使用时候的情景。 我们都知道长方形的面积等于长与宽的积。那当我们用长方形的时候我们会这样用 
Rectangle rectangle = new Rectangle(); 
rectangle.setLength(5); 
rectangle.setWidth(4); 
我们想知道面积是多少我们就可以 
rectangle.getArea(); 
得到的是20,当然结果是非常正确的。 
但想想如果我们把一个正方形的实例给用户用的时候会怎么样 
Rectangle rectangle = new Square(); //注意,这里体显代换原则。用户根本不知道真正的实例是正方形,用户只知道长方形的事情。 
rectangle.setLength(5); 
rectangle.setWidth(4); 
我们想知道面积是多少我们就可以 
rectangle.getArea(); 
得到的结果却是 16 ,这违背了长方形的面积是长与宽之积的原则。用户就不会明白为什么我设置了长是5宽是4得到的答案却是16 ?? 与前提不符 
所以正方形不能代替长方形出现在这个地方。 
也就是说正方形不应当看作是长方形的子类。

之前人们讨论的正方形长方形的问题的关键在哪里?我觉得就在于改动长方形的边的长度。我们可以这么考虑一下,一个长方形的instance的边长应该是可变的吗?我觉得一旦一个长方形的边长改变之后它就成了另一个长方形了(一个新的instance)。所以长方形类里面不应该有改变其边长的方法,一个长方形实例各个的边长应当在new它的时候确定下来,并且它们应当是immutable的。基于这种考虑,我设计的长方形和正方形的类如下所示:
//长方形
public class Rectangle {
  private final int width;
  private final int height;
  
  public Rectangle(int width, int height) {
    this.width = width;
    this.height = height;
  }
  
  public int getWidth() {
    return width;
  }

public int getHeight() {
    return height;
  }
  
  public int getArea() {
    return width*height;
  }
}

//正方形
public class Square extends Rectangle{
  private final int side;
  
  public Square(int side) {
    super(side, side);
    this.side = side;
  }
  
  public int getSide() {
    return side;
  }
}

这种继承关系就既符合现实中的父子关系也遵循LSP。之所以这么设计,我的想法是一个类所具有的方法不应当能够改变其本质。比如有一个Men类,它可以有eat(),sleep(),work(),makeLovewith(Person p)方法,但是如果你在里面定义denatureToWomen(),denatureToEunuch()就很不恰当了,因为这改变了其本质,导致这个Men的实例不再属于Men类(至少已经和现实不吻合)了。除非这两个方法不能改变该实例本质,否则在Men里面定义这两个方法本身就是有问题的。

LSP原则—关于正方形不是长方形的更多相关文章

  1. 连载:面向对象葵花宝典:思想、技巧与实践(32) - LSP原则

    LSP是唯一一个以人名命名的设计原则,并且作者还是一个"女博士"  ======================================================== ...

  2. LSP原则是什么

    如果这篇文章能够帮到您,请给我一个免费的赞,谢谢QWQ! LSP原则并不难,但是地方就会把它说的很啰嗦,如果你对LSP还是感到疑惑,请往下看看. 先上代码: public class Bird { p ...

  3. 设计模式之里氏代换原则(LSP)

    里氏代换原则(Liskov Substitution Principle, LSP) 1 什么是里氏代换原则 里氏代换原则是由麻省理工学院(MIT)计算机科学实验室的Liskov女士,在1987年的O ...

  4. 第2章 面向对象的设计原则(SOLID):2_里氏替换原则(LSP)

    2. 里氏替换原则(Liskov Substitution Principle,LSP) 2.1 定义 (1)所有使用基类的地方必须能透明地使用子类替换,而程序的行为没有任何变化(不会产生运行结果错误 ...

  5. 七、LSP 里氏替换原则

    子类的对象提供了父类的所有行为,且加上子类额外的一些东西(可以是功能,可以是属性).当程序基于父类实现时,如果将子类替换父类而程序不需修改,则说明符合LSP原则. 这个解释看的似懂非懂,再看下面更进一 ...

  6. Liskov替换原则(LSP)

    OCP背后的主要机制是抽象和多态.在静态类型语言中,比如C++和Java,支持抽象和多态的关键机制之一是继承.正是使用了继承,才可以创建实现其基类中抽象方法的派生类.是什么设计规则在支配着这种特殊的继 ...

  7. 架构师之路——里氏替换原则LSP

    定义: 如果对每一个对类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型. 内容: 里氏替换原则通 ...

  8. 3里氏代换原则LSP

    一.什么是里氏代换原则 里氏代换原则(Liskov Substitution Principle): 一个软件实体如果使用的是一个父类的话,那 么一定适用于其子类,而且它察觉不出父类和子 类对象的区别 ...

  9. 深入理解JavaScript系列(8):S.O.L.I.D五大原则之里氏替换原则LSP

    前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第3篇,里氏替换原则LSP(The Liskov Substitution Principle ). 英文原文:http ...

随机推荐

  1. Oralce获取32位随机数

    SELECT SYS_GUID() from dual;

  2. 关于(int argc char **argv)

    演示使用opencv显示一幅图片: #include <iostream> #include <core/core.hpp> #include <highgui/high ...

  3. [LC] 238. Product of Array Except Self

    Given an array nums of n integers where n > 1,  return an array output such that output[i] is equ ...

  4. Java入门级文件下载_学习笔记

    文件下载和上一篇文件上传很像,就不多说了,传一个我写的一个下载歌曲的代码: 下面是Servlet代码: public class DownLoadServlet extends HttpServlet ...

  5. selenium ide几个版本和对应的firefox版本

    最近安装selenium ide折腾了好久,可能是目前还不太熟悉自动化脚本录制的一些知识. 通过最新版firefox59安装的selenium ide 3.0.2录制的脚本不能导出.于是下载了低版本的 ...

  6. php--ip的处理

    1.获取ip /**获取请求ip**/ function _get_request_ip(){ //strcasecmp 比较两个字符,不区分大小写.返回0,>0,<0. if(geten ...

  7. 杂谈php之什么是cgi,fastcgi,fpm,cli,mod

    杂谈PHP极少关注的问题 本话题来自于我使用PHP进行网页爬虫的一次经历.对于一个web开发者来说,PHP解释器本身却知之甚小,实在是惭愧呐! 首先这个话题要从几个提问开始. PHP是什么? 外文名: ...

  8. npm安装依赖太慢问题

    执行 npm install 会发现很慢,可以在安装时手动指定从哪个镜像服务器获取资源,我使用的是阿里巴巴在国内的镜像服务器. 命令如下: npm install --registry=https:/ ...

  9. docker 使用:创建nginx容器

    在上一节中了解了镜像和容器.对于镜像可以这样的理解,镜像相当于一个光盘,里面刻录了一个系统这个系统已经带有相关的服务了. 容器是通过镜像这个光盘安装的一个操作系统,光盘预加了什么服务,容器就有什么服务 ...

  10. Git忽略规则(.gitignore配置)不生效原因和解决

    问题: .gitignore中已经标明忽略的文件目录下的文件,git push的时候还会出现在push的目录中,或者用git status查看状态,想要忽略的文件还是显示被追踪状态. 原因是因为在gi ...