Covarianza e controvarianza (informatica): differenze tra le versioni
(Nessuna differenza)
|
Versione delle 12:39, 16 ago 2017
In informatica, covarianza e controvarianza sono proprietà che caratterizzano alcuni operatori sui tipi. Un operatore è covariante se conserva la relazione di sottotipo, controvariante se la inverte. Prendono il nome dalle omonime proprietà dei funtori in teoria delle categorie.
Definizione
Un operatore F
è covariante se F<T'> ≤ F<T>
quando T' ≤ T
. Analogamente, F
è controvariante se F<T> ≤ F<T'>
quando T' ≤ T
.[1][2]
Varianza e controvarianza sono caratteristiche degli operatori sui tipi che hanno uno o più parametri di tipo e producono un nuovo tipo. Non devono essere confuse con l'ereditarietà dei tipi in sé (es. non ha senso dire che un tipo è covariante o controvariante) o con la compatibilità tra tipi nell'assegnamento (es. in molti linguaggi a oggetti, un oggetto di un sottotipo è sempre assegnabile ad una variabile di un supertipo).[3]
Esempi
Covarianza
Tipicamente, operatori che possono solo leggere oggetti del parametro di tipo possono essere covarianti. Ad esempio in C#, IEnumerable
è covariante e un contenitore enumerabile di un sottotipo (es. IEnumerable<string>
) può essere assegnato ad una variabile il cui tipo è un contenitore enumerabile di un suo supertipo (es. IEnumerable<object>
).
[4] Questo perché i metodi di IEnumerable
possono leggere oggetti dal contenitore ma non scriverli, quindi non c'è rischio di compiere operazioni non typesafe.
// Covarianza
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings; // assegnamento valido
Controvarianza
Analogamente, operatori che possono solo scrivere oggetti del parametro possono essere controvarianti. Ad esempio in C#, template come Action<>
sono controvarianti, in quanto un'azione definita ad esempio su un oggetto può essere eseguita su una stringa, ma non viceversa.[4]
// Controvarianza
// assumendo che esista il metodo `static void SetObject(object o) { }'
Action<object> actObject = SetObject;
Action<string> actString = actObject; // assegnamento valido
Array e contenitori generici
Contenitori generici i cui elementi possono essere modificati sono intrinsecamente nonvarianti,[5] e nei linguaggi in cui sono considerati covarianti questo può permettere operazioni non-typesafe che possono generare errori a runtime.[4]
object[] array = new String[10];
array[0] = 10; // genera un'eccezione a runtime
Funzioni
Oggetti di tipo funzione sono tipicamente controvarianti negli argomenti e covarianti nei valori di ritorno, ovvero è typesafe sostituire una funzione S1 -> T1
con un'altra S2 -> T2
se essa accetta argomenti di un supertipo (S1 ≤ S2
) e restituisce valori di un sottotipo (T2 ≤ T1
).
Tale regola è stata formalizzata da John C. Reynolds[6] e resa popolare da un articolo di Luca Cardelli.[7]
Alcuni linguaggi fanno eccezione, ad esempio in Eiffel la specializzazione dei metodi è covariante negli argomenti.[8] Questo crea quello che nella comunità Eiffel è noto come "catchcall problem", che viola il principio di sostituzione di Liskov e rompe la sicurezza rispetto ai tipi del linguaggio, ma viene considerata dagli autori una caratteristica utile per tradurre in codice i requisiti di un progetto, e sono state proposte e implementate varie tecniche di analisi statica per porre rimedio al problema.[9][10]
Note
- ^
T' ≤ T
denota la relazione d'ordine sui tipi (T'
è sottotipo diT
)., Un operatore è detto bivariante se è sia covariante sia controvariante, nonvariante se non è né invariante né controvariante - ^ Abadi e Cardelli, pp. 21-22.
- ^ Eric Lippert, What's the differnce between covariance and assignment compatibility?, su Microsoft Developer Network, 30 novembre 2009.
- ^ a b c Covariance and Contravariance, su Microsoft Developer Network, 29 luglio 2017.
- ^ Abadi e Cardelli, p. 22.
- ^ John C. Reynolds, The Essence of Algol (ps), Symposium on Algorithmic Languages, North-Holland, 1981.
- ^ Luca Cardelli, A semantics of multiple inheritance (PDF), Semantics of Data Types (International Symposium Sophia-Antipolis, France, June 27 – 29, 1984), Springer, 1984.(Longer version in Information and Computation, 76(2/3): 138-164, February 1988.)
- ^ ET: Inheritance, su eiffel.org.
- ^ Bertrand Meyer, Static Typing (PDF), October 1995.
- ^ Type-safe covariance: Competent compilers can catch all catcalls (PDF), su se.ethz.ch, April 2003. URL consultato il 23 May 2013.
Bibliografia
- M. Abadi, A Theory of Objects, Springer New York, 2012, ISBN 978-1-4419-8598-9.