LSP原则—关于正方形不是长方形
长方形有二个属性长和宽。并有一个设置长的方法和设置宽的方法,还有一个求面积的方法.
像下面
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原则—关于正方形不是长方形的更多相关文章
- 连载:面向对象葵花宝典:思想、技巧与实践(32) - LSP原则
LSP是唯一一个以人名命名的设计原则,并且作者还是一个"女博士" ======================================================== ...
- LSP原则是什么
如果这篇文章能够帮到您,请给我一个免费的赞,谢谢QWQ! LSP原则并不难,但是地方就会把它说的很啰嗦,如果你对LSP还是感到疑惑,请往下看看. 先上代码: public class Bird { p ...
- 设计模式之里氏代换原则(LSP)
里氏代换原则(Liskov Substitution Principle, LSP) 1 什么是里氏代换原则 里氏代换原则是由麻省理工学院(MIT)计算机科学实验室的Liskov女士,在1987年的O ...
- 第2章 面向对象的设计原则(SOLID):2_里氏替换原则(LSP)
2. 里氏替换原则(Liskov Substitution Principle,LSP) 2.1 定义 (1)所有使用基类的地方必须能透明地使用子类替换,而程序的行为没有任何变化(不会产生运行结果错误 ...
- 七、LSP 里氏替换原则
子类的对象提供了父类的所有行为,且加上子类额外的一些东西(可以是功能,可以是属性).当程序基于父类实现时,如果将子类替换父类而程序不需修改,则说明符合LSP原则. 这个解释看的似懂非懂,再看下面更进一 ...
- Liskov替换原则(LSP)
OCP背后的主要机制是抽象和多态.在静态类型语言中,比如C++和Java,支持抽象和多态的关键机制之一是继承.正是使用了继承,才可以创建实现其基类中抽象方法的派生类.是什么设计规则在支配着这种特殊的继 ...
- 架构师之路——里氏替换原则LSP
定义: 如果对每一个对类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型. 内容: 里氏替换原则通 ...
- 3里氏代换原则LSP
一.什么是里氏代换原则 里氏代换原则(Liskov Substitution Principle): 一个软件实体如果使用的是一个父类的话,那 么一定适用于其子类,而且它察觉不出父类和子 类对象的区别 ...
- 深入理解JavaScript系列(8):S.O.L.I.D五大原则之里氏替换原则LSP
前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第3篇,里氏替换原则LSP(The Liskov Substitution Principle ). 英文原文:http ...
随机推荐
- 将list转成tree
using System;using System.Collections.Generic;using System.Linq; namespace Infrastructure{ /// <s ...
- ZooKeeper基本讲解及使用
本文摘录于:http://blog.51cto.com/tchuairen/1859494:https://blog.csdn.net/peace1213/article/details/525714 ...
- RNA sequence单分子直测技术
生命组学 按照功能分类遗传物质,可能的分类有系统流.操作流.平衡流等等.下面是使用该理论解释DNA与RNA的关系: DNA和RNA有很大不同,DNA存储遗传信息,作为生命活动的最内核物质,如同操作系统 ...
- linux上hosts文件如何配置
linux上hosts文件如何配置 一.什么是host Hosts是一个没有扩展名的系统文件,其基本作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,当用户在浏览器中输入一个需要登 ...
- C++ 部分STL
map map可以理解为一个数组(但实质上并不是,只是方便理解),我们一般的数组不管定义成什么类型他的下标都是整型(int),map和这些数组的区别是他的下标可以是其他类型,由自己定义.map的创建. ...
- Redis 事物、悲观、乐观锁 (详细)
1,概论 事物这东西相信大家都不陌生吧,在学习Spring,Mybatis等框架中, 只要是涉及到数据存储和修改的,都会有事物的存在, 废话就不多说了下面我们来简单的介绍下Redis事物以及锁. 2, ...
- 接口测试-chap6-获取页面动态token
1.在发起某些请求时,可能会要求必须是从某个页面进行请求,此时会验证页面的token 2.这个token是动态生成的,每次请求时值都是不同的, 不可以通过fiddler抓取的值作为固定值传入,通过fi ...
- bzoj1432_[ZJOI2009]Function
题目描述 有n 个连续函数fi (x),其中1 ≤ i ≤ n.对于任何两个函数fi (x) 和fj (x),(i != j),恰好存在一个x 使得fi (x) = fj (x),并且存在无穷多的x ...
- react-native保存图片Android实现方法
/图片的路径格式为远程请求, 例如:'http://xxx:8080/image.jpg' import { Platform, PermissionsAndroid, NativeModules } ...
- JavaScript中点击按钮弹出新的浏览器窗口
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.js * 作者:常轩 * 微信公众号:Worldhel ...