Videa Blog

SOLID principy: Liskovové princip zastoupení

Michal Katuščák  

Liskovové princip zastupitelnosti je definovám jako tahle na první podhled děsivá rovnice:

Nechť Φ(x) je vlastnost prokazatelná objektu x typu T. Potom Φ(y) jsou pravdivé pro objekty y typu S, kde S je potomkem T.

Trochu lidskými slovy ale říká:

Supertyp by měl být plně nahraditelný podtypem.

Video (1:46)

Video na Youtube

Což je zjednoduše to, že potomek třídy by mě zachovat stejný přístup k metodám, které má i rodičovská třída.

Řekněme, že máme takovýto kód:

<?php

class Response
{
    protected $data;

    public function render()
    {
        return $this->data;
    }
}

class JsonResponse extends Response
{
    public function render($data)
    {
        return json_encode($data);
    }
}

class ResponseRender
{
    public function render(Response $response)
    {
        echo $response->render();
    }
}

Pokud bych do metody render() třídy ResponseRender jako parametr vložit instanci třídy JsonResponse, skončilo by to chybou, protože ta požaduje v metodě render() data, což její rodičovská třída nevyžaduje. To znamená, že Response není plně nahraditelný třídou JsonResponse.

Můžeme sice připravit podmínku, kde se typ JsonResponse bude kontrolovat, ale problém tím není zcela vyřešen, protože kdekoli jinde stále nebude Response zcela nahraditelná potomkem JsonResponse. Navíc bychom tím porušili princip otevřenosti a uzavřenosti.

Správným řešením je sjednotit přístup k metodám tříd tak, aby byla rodičovská třída plně zastupitelná:

<?php

class Response
{
    protected $data;

    public function render()
    {
        return $this->data;
    }
}

class JsonResponse extends Response
{
    public function render()
    {
        return json_encode($this->data);
    }
}

class ResponseRender
{
    public function render(Response $response)
    {
        echo $response->render();
    }
}

Zdroje