Kurzusok
/
PHP
PHP
/
Tanterv
/
Kovariancia és kontravariancia
Ko

Kovariancia és kontravariancia ebben a kurzusban: PHP

{one: "1 feladat", other: "%{count} feladat"}

A(z) Kovariancia és kontravariancia fogalomról

Kovariancia és kontravariancia

Amikor uniótípusokat használsz, tisztában kell lenned a kovariancia és a kontravariancia fogalmával. Ezeket a dokumentáció is elmagyarázza, de talán ezek a példák is segítenek.

Tegyük fel, hogy van egy Calculator osztályunk, amely az előző példához hasonló függvényt használ:

class Calculator
{
    public function add(int|float $x, int|float $y): int|float
    {
        return $x + $y;
    }
}

Ha kiterjeszted az osztályt, megváltoztathatod a paramétertípusokat és a visszatérési típusokat, de csak a következő szabályok szerint.

Először is, a paramétertípusok „szélesebbek” lehetnek, ami azt jelenti, hogy több típust fogadhatnak el, mint az ősosztály. Például ez megengedett:

class StringCalc extends Foo
{
    public function add(float|int|string $x, float|int|string $y): int|float
    {
        if (!is_numeric($x) || !is_numeric($y)) {
            throw new \InvalidArgumentException('$x and $y must be numeric');
        }
        return $x + $y;
    }
}

A StringCalc-et behelyettesíthetnénk az eredeti Calculator helyére, és minden továbbra is működne. A hívó továbbra is be tudná küldeni azt a float vagy int értéket, amit eredetileg is, és a visszatérési típus is a várt int vagy float lenne.

Hasonlóképpen szűkítheted a visszatérési típust, azaz konkrétabbá teheted azáltal, hogy típusokat veszel ki az unióból. Ez a példa kihasználja ezt a szabályt:

class IntCalc extends Calculator
{
    public function add(float|int $x, float|int $y) : int
    {
        return (int)($x + $y);
    }
}

Mivel az IntCalc továbbra is elfogad int és float értéket, gond nélkül helyettesítheti az eredeti Calculator-t.

Ha többet szeretnél megtudni arról, mi megengedett és mi nem, olvasd el a Liskov-féle helyettesítési elv (LSP) leírását.

Arra, hogy mi nem megengedett, nézd meg az alábbi InvalidCalc osztályt:

class InvalidCalc extends Calculator
{
    public function add(int $x, int $y) : int|float|string
    {
        // Declaration must be compatible with Calculator->add(x: float|int, y: float|int)

        // Return type declaration must be compatible with Calculator->add(x: float|int, y: float|int) : float|int
    }
}

Az InvalidCalc osztály nem fog lefordulni, és két problémája is van. Mivel szűkítette a paraméterként elfogadható típusokat, az InvalidCalc nem helyettesítheti az eredeti Calculator-t, mert már nem fogad el float értéket. Ráadásul most már string-et is visszaadhat, ami szintén nincs benne az eredeti osztály megengedett visszatérési típusai között.

Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg