Ich möchte ein Beispiel mit Rechtecken und Quadraten zeigen:Warum unveränderliche Objekte das Likov Substitutionsprinzip erfüllen können?
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
}
}
}
Wenn ich eine Instanz von Square
statt Rectangle
in Verfahren ersetzen LSPTest das Verhalten meines Programms geändert. Dies steht im Gegensatz zum LSP.
Ich habe gehört, dass unveränderliche Objekt erlauben, dieses Problem zu lösen. Aber warum?
Ich habe Beispiel geändert. ich hinzufügen Konstruktor in Rectangle
:
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
Dann änderte ich Setter:
public Rectangle setWidth(int width) {
return new Rectangle(width, this.height);
}
public Rectangle setHeight(int height) {
return new Rectangle(this.width, height);
}
Nun sieht Square
wie:
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);
}
}
Und hier der Client-Code ist:
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");
}
}
}
Die gleichen Probleme bleiben. Was ist der Unterschied, ob das Objekt selbst geändert wird oder ein neues Objekt zurückgegeben wird? Das Programm verhält sich immer noch anders für die Basisklasse und die Unterklasse.
Was macht Sie denken, unveränderliche Objekte inhärent die LSP satisty? (Hinweis, sie nicht). – jtahlborn
Ich stimme @jtahlborn zu. Und zu versuchen, ein unveränderliches Objekt mit einem Setter zu implementieren, der ein neues Objekt zurückgibt, scheint mir ziemlich verwirrend. –
Ihre quadratische unveränderliche Implementierung ist hier das Problem. Es sollte nicht zwei Argumente in seinem Konstruktor nehmen, sondern nur einen. Und es sollte SetWidth und SetHeight nicht überschreiben. Der Basisklasse setWidth() - Kontrakt soll ein Rectangle mit der gleichen Höhe wie das Original und die angegebene Breite zurückgeben. Es gibt keinen Grund, das in Square zu überschreiben: die Basismethode ist auch für ein Quadrat korrekt: Es gibt kein Quadrat zurück. –