Tracce
/
PHP
PHP
/
Programma
/
Covarianza e controvarianza
Co

Covarianza e controvarianza in PHP

{one: "1 esercizio", many: "%{count} esercizi", other: "%{count} esercizi"}

Informazioni su Covarianza e controvarianza

Covarianza e controvarianza

Quando usi i tipi union, devi conoscere i concetti di covarianza e controvarianza. Sono spiegati nella documentazione, ma questi esempi potrebbero aiutarti.

Supponiamo di avere una classe Calculator che usa una funzione come nell'esempio precedente:

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

Se estendi la classe, puoi modificare i tipi dei parametri e i tipi restituiti, ma solo secondo le regole seguenti.

Primo, i tipi dei parametri possono essere «più ampi», il che significa che possono accettare più tipi rispetto alla classe base. Per esempio, questo è consentito:

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;
    }
}

Potremmo sostituire StringCalc al posto di un Calculator originale e tutto funzionerebbe ancora. Chi chiama potrebbe ancora passare il float o l'int che poteva passare in origine, e il tipo restituito sarebbe ancora l'int o il float previsto.

Allo stesso modo, puoi restringere il tipo restituito, cioè renderlo più specifico rimuovendo tipi dall'unione. Questo esempio sfrutta questa regola:

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

Dato che IntCalc accetta ancora int e float, può ancora sostituire un Calculator originale senza problemi.

Per saperne di più su ciò che è consentito e ciò che non lo è, puoi consultare il Principio di sostituzione di Liskov (LSP).

Per un esempio di ciò che non sarebbe consentito, dai un'occhiata a InvalidCalc qui sotto:

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
    }
}

La classe InvalidCalc non verrà compilata e presenta due problemi. Riducendo ciò che è consentito come parametro, InvalidCalc non potrebbe sostituire il Calculator originale perché non accetta più float. Inoltre, ora potrebbe restituire una string, che non rientra nemmeno tra i tipi restituiti consentiti della classe originale.

Modifica tramite GitHub Il collegamento si apre in una nuova finestra o scheda