日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Liskov替换原则(LSP)

發布時間:2024/7/23 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Liskov替换原则(LSP) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Liskov替換原則(The Liskov Substitution Principle)

子類型(subtype)必須能夠替換掉它們的基類型(base type)。

一個違反LSP的簡單例子

public class AntiLspDemo {public void drawShape(final Shape shape) {if (shape.getItsType() == ShapeType.Square) {final Square square = (Square) shape;square.draw();} else if (shape.getItsType() == ShapeType.Circel) {final Circle circle = (Circle) shape;circle.draw();}} }enum ShapeType {/*** 正方形.*/Square,/*** 圓形.*/Circel }class Point {private double x;private double y;// get/set... }class Shape {private ShapeType itsType;/*** 獲取itsType.* @return the itsType*/public ShapeType getItsType() {return itsType;}/*** 設置itsType.* @param newItsType the itsType to set*/public void setItsType(ShapeType newItsType) {itsType = newItsType;}}class Circle extends Shape {private Point itsCenter;private double itsRadius;public Circle() {this.setItsType(ShapeType.Circel);}public void draw() {System.out.println("繪制Circle...");} }class Square extends Shape {private Point itsTopLeft;private double itsSide;public Square() {this.setItsType(ShapeType.Square);}public void draw() {System.out.println("繪制Square...");} }

正方形和矩形,更微妙的違規

? ? ? ? 我們經常說繼承是IS-A(“是一個”)關系。如果一個新類型的對象被認為和一個已有類的對象之間滿足IS-A關系,那么這個新對象的類應該從這個已用對象的類派生。

? ? ? ? 一個正方形是一個矩形,所以Square類就應該派生在Rectangle類。不過,這將帶來一些微妙但極為值得重視的問題。

public class Rectangle {/*** 左上角坐標.*/private Point topLeft;/*** 寬度.*/private double width;/*** 高度.*/private double height;/*** 獲取topLeft.* @return the topLeft*/public Point getTopLeft() {return topLeft;}/*** 設置topLeft.* @param newTopLeft the topLeft to set*/public void setTopLeft(Point newTopLeft) {topLeft = newTopLeft;}/*** 獲取width.* @return the width*/public double getWidth() {return width;}/*** 設置width.* @param newWidth the width to set*/public void setWidth(double newWidth) {width = newWidth;}/*** 獲取height.* @return the height*/public double getHeight() {return height;}/*** 設置height.* @param newHeight the height to set*/public void setHeight(double newHeight) {height = newHeight;}}public class Square extends Rectangle {public void setWidth(double width) {super.setWidth(width);super.setHeight(width);}public void setHeight(double height) {super.setWidth(height);super.setHeight(height);} }

真正的問題

? ? ? ? Square類沒有違反正方形的不變性,但是Square派生自Rectangle,Square類違反了Rectangle類的不變性。

public void g(Rectangle r) {r.setWidth(5);r.setHeight(4);assert(r.area() == 20) }

有效性并非本質屬性

? ? ? ? 一個模型,如果孤立地看,并不具有真正意義上的有效性。模型的有效性只能通過它的Client程序來體現。這又是一個實踐TDD的好理由。

IS-A是關于行為的

? ? ? ? 對于那些不是g的調用者而言,正方形可以是長方形,但是從g的角度,Square對象絕對不是Rectangle對象。Square對象的行為方式和函數g所期望的Rectangle對象的行為方式不相容。從行為方式的角度來看,Square不是Rectangle,對象的行為方式才是軟件真正所關注的。

基于契約設計

? ? ? ? 基于契約設計(Design By Contract),類的編寫者顯示地規定針對該類的契約。契約是通過為每個方法聲明的前置條件(preconditions)和后置條件(postconditions)來指定的。要執行一個方法,前置條件必須為真。執行完畢后,保證后置條件為真。?

Rectangle.setWidth(double w)的后置條件: assert((width == w) && (height == old.height));

? ? ? ? 派生類的前置條件和后置條件規則是:

在重新聲明派生類中的例程(routine)時,

只能使用相等或更弱的前置條件,只能使用相等或更強的后置條件。

總結

以上是生活随笔為你收集整理的Liskov替换原则(LSP)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。