(Ci scusiamo prima, con C # è un po 'arrugginito)
Come menzionato nelle altre risposte, la grande caratteristica dei tipi di ritorno convenzionali è la possibilità di sostituire le funzioni virtuali con funzioni che restituiscono un tipo di ritorno più specifico.
Ad esempio:
public class Foo
{
virtual public Foo getCopy(); { //Create a copy of this Foo and return it }
}
Il metodo getCopy()
restituisce una copia del Foo
su cui è stato invocato, finora, così buono. Aggiungiamo una classe che eredita da Foo
.
public class Bar : Foo
{
override public Foo getCopy(); { //Create a copy of this Bar and return it as a Foo }
}
Notare che senza tipi di ritorno covarianti dobbiamo dichiarare che restituiamo un Foo
(ufficialmente) invece di un Bar
(anche se in realtà restituiamo un Bar
). Questo potrebbe non essere così male finché non scrivi il codice seguente.
//Copying things
Foo myFoo;
Foo myOtherFoo = myFoo.getCopy();
Bar myBar;
Bar myOtherBar = myBar.getCopy(); //Compiler error - getCopy() returns a Foo
Anche se sai che myBar è un Bar
, e che (in realtà) ottieni un Bar
dal getCopy()
di myBars, devi eseguire il cast del valore restituito per farlo compilare. Peggio ancora, è una potenziale fonte di bug ...
public class Baz : Foo
{
override public Foo getCopy(); { //Create a copy of this Baz and return it as a Foo }
}
//Copying more things
Foo myFoo;
Foo myOtherFoo = myFoo.getCopy();
Bar myBar;
Bar myOtherBar = myBar.getCopy() as Bar;
Baz myBaz;
Baz myOtherBaz = myBar.getCopy() as Baz; //Whoops
Hai notato l'errore? Senza valori di ritorno covarianti si potrebbe notare solo durante il runtime (quando il programma si blocca), con loro il compilatore può dirti in fase di compilazione: No, non può funzionare.
In sintesi: i valori di restituzione covarianti ti consentono di scrivere un codice più breve, più preciso e più sicuro.