Я хочу показать пример с прямоугольниками и квадратами:Почему неизменные объекты позволяют соблюдать Принцип замещения Лискова?
class Rectangle {
private int width;
private int height;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int area() {
return width * height;
}
}
class Square extends Rectangle{
@Override
public void setWidth(int width){
super.setWidth(width);
super.setHeight(width);
}
@Override
public void setHeight(int height){
super.setHeight(height);
super.setWidth(height);
}
}
public class Use {
public static void main(String[] args) {
Rectangle sq = new Square();
LSPTest(sq);
}
public static void LSPTest(Rectangle rec) {
rec.setWidth(5);
rec.setHeight(4);
if (rec.area() == 20) {
// do Something
}
}
}
Если я заменить экземпляр Square
вместо Rectangle
в методе LSPTest поведение моей программы будет изменено. Это противоречит LSP.
Я слышал, что неизменный объект позволяет решить эту проблему. Но почему?
Я изменил пример. добавить конструктор в Rectangle
:
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
Затем я изменил сеттеры:
public Rectangle setWidth(int width) {
return new Rectangle(width, this.height);
}
public Rectangle setHeight(int height) {
return new Rectangle(this.width, height);
}
Теперь Square
выглядит следующим образом:
class Square{
public Square() {
}
public Square(int width, int height) {
super(width, height);
}
@Override
public Rectangle setWidth(int width) {
return new Rectangle(width, width);
}
@Override
public Rectangle setHeight(int height) {
return new Rectangle(height, height);
}
}
А вот код клиента:
public class Use {
public static void main(String[] args) {
Rectangle sq = new Square(4, 4);
LSPTest(sq);
}
public static void LSPTest(Rectangle rec) {
rec = rec.setHeight(5);
if (rec.area() == 20) {
System.out.println("yes");
}
}
}
Те же проблемы остаются. В чем разница, изменяется ли сам объект или возвращается новый объект. Программа по-прежнему ведет себя по-разному для базового класса и подкласса.
Что заставляет вас думать, что непреложные объекты неотъемлемо украшены LSP? (намек, они этого не делают). – jtahlborn
Я согласен с @jtahlborn. И попытка реализовать неизменяемый объект с сеттером, который возвращает новый объект, кажется мне довольно запутанной. –
Проблема с квадратом неизменяема. Он не должен принимать два аргумента в своем конструкторе, но только один. И он не должен переопределять setWidth и setHeight. Контракт baseWidth() должен возвращать прямоугольник с той же высотой, что и исходный и заданная ширина. Нет причин переопределять это на Square: базовый метод также подходит для Square: он просто не возвращает квадрат. –