Zasada zastąpienia Liskova

Zasada zastąpienia Liskova jest jedną z pięciu zasad dobrego programowania SOLID. Ogólna definicja mówi, że jeżeli obiekt A jest podtypem obiektu B i jeśli obiekt A jest traktowany jak B, to powinien się on zachowywać jak obiekt B.

Klasycznych przykładem jest kwadrat i prostokąt. W myśl tej zasady: jeśli kwadrat jest podtypem prostokąta i jeśli kwadrat traktujemy jak prostokąt (tzn. stosujemy wzór na pole prostokąta wobec kwadratu), to otrzymamy prawidłowy wynik pola figury.

W programowaniu obiektowym zasada Liskova brzmi nieco inaczej: klasy pochodne nie powinny w żaden sposób naruszyć definicji klasy bazowej.

Aby lepiej zrozumieć jak zasada Liskova wygląda w programowaniu obiektowym, najpierw klasyczny przykład złamania zasady Liskova:

class Rectangle {
    
    
    public $width, $height;
    
    
    public function setWidth($width)
    {
        $this->width = $width;
    }
    
    public function setHeight($height)
    {
        $this->height = $height;
    }
    
    
    public function area()
    {
        return $this->width * $this->height;
    }
    
}


class Square extends Rectangle  {
    
    
    public function setWidth($width)
    {
        $this->width = $width;
        $this->height = $width;
    }
    
    public function setHeight($height)
    {
        $this->height = $height;
        $this->width = $height;
    }
    
    
}


$obj = new Square; // obiekt utworzony gdzieś w kodzie, np. poprzez wzorzec Dependency Injection

// początek kodu klienckiego
if($obj instanceof Rectangle) // warunek wykonuje się, a więc naruszenie definicji klasy bazowej (próbujemy prostokątowi przypisać równe boki)
{
    $obj->setWidth(2);
    $obj->setHeight(3);
}


echo $obj->area(); // programista otrzyma wynik 9 zamiast 6, lecz błąd może być trudny do zauważenia w przypadku bardziej skomplikowanych obliczeń

Zostań Profesjonalistą W Tworzeniu Aplikacji Webowych! Zapisz Się Na Kurs Laravel nauczysz się również tworzyć aplikacje hybrydowe na smartfony

Problemem jest tutaj nieprawidłowe dziedziczenie, którego albo należy się pozbyć, albo zastosować nadklasę abstrakcyjną, po której odziedziczą obie figury, czyli tak skonstruować dziedziczenie, aby w kodzie klienckim nie doszło do nieporozumień:

abstract class Shape {
    
    
    public $width, $height;
    
    
    public function setWidth($width)
    {
        $this->width = $width;
    }
    
    public function setHeight($height)
    {
        $this->height = $height;
    }
    
    
    public function area()
    {
        return $this->width * $this->height;
    }
    
}


class Rectangle extends Shape {}
    

class Square extends Shape  {
    
    
    public function setWidth($width)
    {
        $this->width = $width;
        $this->height = $width;
    }
    
    public function setHeight($height)
    {
        $this->height = $height;
        $this->width = $height;
    }
    
    
}


$obj = new Square;  // obiekt utworzony gdzieś w kodzie, np. poprzez wzorzec Dependency Injection

// początek kodu klienckiego
if($obj instanceof Rectangle)
{
    $obj->setWidth(2);
    $obj->setHeight(3);
}


echo $obj->area(); // teraz otrzymamy 0 czyli warunek powyżej się nie wykonał, programista zorientuje się, że coś jest nie tak

 

zapisz się na kurs Laravela >>>> lub program partnerski
Share

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *