Spis Treści
Trochę teorii
Trzecią już zasadą, którą omówię w cyklu artykułów o SOLID będzie zasada podstawiania Liskov. Zasada ta jest powiązana bezpośrednio z mechanizmem dziedziczenia a jej treść przedstawia się następująco:
Funkcje, które używają wskaźników lub referencji do klas bazowych, muszą być w stanie używać również obiektów klas dziedziczących po klasach bazowych, bez dokładnej znajomości tych obiektów
Wikipedia
Wygląda groźnie, prawda? Myślę, że można te zasadę przedstawić nieco prościej i bardziej intuicyjnie:
Tam gdzie używasz klasy bazowej, powinieneś móc użyć klasy dziedziczącej po niej
Słynny przykład z kwadratem
Najprostszym i najlepiej pokazującym te zasadę jest przykład z obliczaniem pola prostokąta i kwadratu. Tworzymy bazową klasę prostokąta z metodą obliczającą pole powierzchni figury oraz klasę kwadrat dziedziczącą po prostokącie (w końcu kwadrat jest prostokątem):
public class Rectangle {
protected int width;
protected int height;
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public int calculateArea() {
return width * height;
}
}
public class Square extends Rectangle {
public void setWidth(int width) {
this.width = width;
this.height = width;
}
public void setHeight(int height) {
this.width = height;
this.height = height;
}
}
A teraz skorzystajmy z naszych klas według poniższego kodu i zastanówmy się jakie wyniki otrzymamy:
public class Launcher {
public static void main(String[] args) {
//make operations using base class
Rectangle rectangle = new Rectangle();
rectangle.setWidth(5);
rectangle.setHeight(10);
System.out.println(rectangle.calculateArea());
//make operations using polymorphism
Rectangle rectangleSquare = new Square();
rectangleSquare.setWidth(5);
rectangleSquare.setHeight(10);
System.out.println(rectangleSquare.calculateArea());
//make operations using inherited class
Square square = new Square();
square.setWidth(5);
square.setHeight(10);
System.out.println(square.calculateArea());
}
}
Jeśli już przeanalizowaliście powyższy kod to z pewnością zauważycie, że coś tu nie gra. O ile z pierwszego równania otrzymamy poprawną wartość 50, to z kolejnych otrzymamy wartość 100 i znów 100.
Jest to przykład łamania zasady podstawiania Liskov – wykonanie kodu powoduje różne efekty w zależności od referencji na klasę bazową czy też potomną. A więc jeszcze raz: Klasa potomna nie powinna zmieniać zachowania klasy bazowej.
Treść jest klarowna, dobrze zorganizowana i pełna przydatnych wskazówek. Autor doskonale wyjaśnia kluczowe zagadnienia. Może warto by dodać więcej przykładów praktycznych. Pomimo tego, tekst jest niezwykle edukacyjny i inspirujący.
Pingback: SOLID - podstawa programowania obiektowego – Wojciech Siwek
Możliwość komentowania została wyłączona.