Варіантність — у програмуванні, спосіб перенесення наслідування типів на нові типи попередніми (контейнери, узагальнені типи, ).
Терміни виникли від термінів теорії категорій «коваріантний» та «контраваріантний» функтор.
Визначення
В системі типів мови програмування, конструктор типів є:
- коваріантним — якщо він зберігає порядок типів (від похідних до базового);
- контраваріантним — якщо він змінює порядок типів на протилежний;
- біваріантним — якщо прямий і обернений порядок є справедливими одночасно.
- інваріантним чи неваріантним — якщо він не підпадає під попередні варіанти.
C# приклади
Наприклад, в C#, якщо Cat
це підтип Animal
, тоді:
IEnumerable<Cat>
це підтипIEnumerable<Animal>
. Підтипність збережена, боIEnumerable<T>
коваріантний поT
.Action<Animal>
підтипAction<Cat>
. Підтипність обернута, боAction<T>
контраваріантний поT
.- Ані
IList<Cat>
, аніIList<Animal>
не є підтипом іншого, боIList<T>
інваріантний поT
.
Варіантність узагальнених інтерфейсів C# визначається через використання атрибута out
(коваріантний) або in
(контраваріантний) для (нуля чи більше) його параметрів типів. Для кожного промаркованого таким чином параметра, компілятор перевіряє, не дозволячи жодного порушення, що використання глобально цілісне. Згадані інтерфейси означені як IEnumerable<out T>
, Action<in T>
і IList<T>
. Типи з більш ніж одним параметром типом можуть вказувати різні варіантності для різних параметрів типів. Наприклад, тип делегат Func<in T, out TResult>
представляє функцію з контраваріантним входовим параметром типом T
і коваріантним параметром типу результату TResult
.
Варіантність контейнерів
Якщо типи Cat
та Dog
наслідують тип Animal
, конструктором масивів з типу Animal
утворимо тип Animal[]
("масив звірів"). Ми можемо використовувати його:
- коваріантно: вважаючи що
Cat[]
є представникомAnimal[]
- контраваріантно: вважаючи що
Animal[]
є представникомCat[]
- інваріантно: вважаючи що
Animal[]
не є представникомCat[]
а такожCat[]
не є представникомAnimal[]
.
Залежно від типу операцій, що будуть проводитись над масивом ми можемо використовувати різну варіантність:
- якщо тільки читати елементи масиву, то безпечно використовувати його коваріантно, оскільки
Cat
є представникомAnimal
; - якщо тільки записувати чи передавати елементи масиву то безпечно використовувати його контраваріантно, щоб не було можливості в масив
Cat[]
записати елемент типуDog
; - якщо ж потрібно читати та записувати елементи масиву, то безпечно використовувати його тільки інваріантно. Також можна реалізувати два незалежні інтерфейси коваріантний Producer<T> для читання та контраваріантний Consumer<T> для запису елементів.
Варіантність функційних типів
Функційні типи є коваріантними по типу результата та контраваріантними по типах аргументів.
Тобто функції типу Cat->Cat
та Animal->Animal
наслідують тип Cat->Animal
та можуть безпечно використовуватись там де очікувався базовий тип.
Варіантність при успадковуванні
починаючи зі стандарту 1998 року підтримує коваріантність при заміщенні віртуальних методів:
class X {}; class Y : public X {}; class A { public: virtual X* f() { return new X; } }; class B : public A { public: virtual Y* f() { return new Y; } // заміщуючи метод, можна повернути уточнений тип результату };
В наступній таблиці зібрана варіантність при заміщенні методів для різних мов програмування.
тип аргумента | тип результату | |
---|---|---|
C# | інваріантний | інваріантний |
(з 1998), Java (з J2SE 5.0), Scala, D | інваріантний | коваріантний |
контраваріантний | коваріантний | |
Eiffel | коваріантний | коваріантний |
Варіантність шаблонних типів
В деяких мовах програмування, що підтримують , можливо вказати варіантність шаблонного типу по параметру. Це можливо:
- при декларації шаблонного типу (як в C#) чи
- при створенні (використанні) конкретного типу на основі шаблонного (як в Java).
Задання варіантності при декларації
- в C# це можливо тільки для інтерфейсів (ключовими кловами
out
таin
), - в Scala та OCaml (ключовими кловами
+
та-
).
Якщо варіантність не задана, то тип буде вважатись інваріантним.
- Приклад
interface IEnumerator<out T> { T Current { get; } bool MoveNext(); }
IEnumerator<Cat>
буде вважатись успадкованим від IEnumerator<Animal>
.
Задання варіантності при використанні
Задання варіантності при створенні кожного конкретного типу є більш гнучким. Воно дозволяє автору класа не декларувати декілька інтерфейсів з різною варіантністю. В Java варіантність задається разом із заданням обмежуючого типу:
List<? extends Animal>
буде коваріантним типу елемента;List<? super Animal>
буде контраваріантним типу елемента.
При заданні варіантності буде заборонено використовувати методи класу з відмінною варіантністю.
Джерела
- http://msdn.microsoft.com/ru-ru/library/dd799517.aspx [ 24 Грудня 2015 у Wayback Machine.] Коваріантність і контраваріантність в шаблонах.
- http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx [Архівовано 28 Червня 2013 у WebCite] Covariance and Contravariance in C#, Part Two. Eric Lippert.
- Func<T, TResult> Delegate [ 19 Серпня 2017 у Wayback Machine.] - MSDN Documentation
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
U Vikipediyi ye statti pro inshi znachennya cogo termina Kovariantnist i kontravariantnist Variantnist u programuvanni sposib perenesennya nasliduvannya tipiv na novi tipi poperednimi kontejneri uzagalneni tipi Termini vinikli vid terminiv teoriyi kategorij kovariantnij ta kontravariantnij funktor ViznachennyaV sistemi tipiv movi programuvannya konstruktor tipiv ye kovariantnim yaksho vin zberigaye poryadok tipiv vid pohidnih do bazovogo kontravariantnim yaksho vin zminyuye poryadok tipiv na protilezhnij bivariantnim yaksho pryamij i obernenij poryadok ye spravedlivimi odnochasno invariantnim chi nevariantnim yaksho vin ne pidpadaye pid poperedni varianti C prikladi Napriklad v C yaksho Cat ce pidtip Animal todi IEnumerable lt Cat gt ce pidtip IEnumerable lt Animal gt Pidtipnist zberezhena bo IEnumerable lt T gt kovariantnij po T Action lt Animal gt pidtip Action lt Cat gt Pidtipnist obernuta bo Action lt T gt kontravariantnij po T Ani IList lt Cat gt ani IList lt Animal gt ne ye pidtipom inshogo bo IList lt T gt invariantnij po T Variantnist uzagalnenih interfejsiv C viznachayetsya cherez vikoristannya atributa out kovariantnij abo in kontravariantnij dlya nulya chi bilshe jogo parametriv tipiv Dlya kozhnogo promarkovanogo takim chinom parametra kompilyator pereviryaye ne dozvolyachi zhodnogo porushennya sho vikoristannya globalno cilisne Zgadani interfejsi oznacheni yak IEnumerable lt out T gt Action lt in T gt i IList lt T gt Tipi z bilsh nizh odnim parametrom tipom mozhut vkazuvati rizni variantnosti dlya riznih parametriv tipiv Napriklad tip delegat Func lt in T out TResult gt predstavlyaye funkciyu z kontravariantnim vhodovim parametrom tipom T i kovariantnim parametrom tipu rezultatu TResult Variantnist kontejnerivYaksho tipi Cat ta Dog nasliduyut tip Animal konstruktorom masiviv z tipu Animal utvorimo tip Animal masiv zviriv Mi mozhemo vikoristovuvati jogo kovariantno vvazhayuchi sho Cat ye predstavnikom Animal kontravariantno vvazhayuchi sho Animal ye predstavnikom Cat invariantno vvazhayuchi sho Animal ne ye predstavnikom Cat a takozh Cat ne ye predstavnikom Animal Zalezhno vid tipu operacij sho budut provoditis nad masivom mi mozhemo vikoristovuvati riznu variantnist yaksho tilki chitati elementi masivu to bezpechno vikoristovuvati jogo kovariantno oskilki Cat ye predstavnikom Animal yaksho tilki zapisuvati chi peredavati elementi masivu to bezpechno vikoristovuvati jogo kontravariantno shob ne bulo mozhlivosti v masiv Cat zapisati element tipu Dog yaksho zh potribno chitati ta zapisuvati elementi masivu to bezpechno vikoristovuvati jogo tilki invariantno Takozh mozhna realizuvati dva nezalezhni interfejsi kovariantnij Producer lt T gt dlya chitannya ta kontravariantnij Consumer lt T gt dlya zapisu elementiv Masivi ye kovariantnimi v Java C ta invariantnimi v C Variantnist funkcijnih tipivFunkcijni tipi ye kovariantnimi po tipu rezultata ta kontravariantnimi po tipah argumentiv Tobto funkciyi tipu Cat gt Cat ta Animal gt Animal nasliduyut tip Cat gt Animal ta mozhut bezpechno vikoristovuvatis tam de ochikuvavsya bazovij tip Variantnist pri uspadkovuvanniC pochinayuchi zi standartu 1998 roku pidtrimuye kovariantnist pri zamishenni virtualnih metodiv class X class Y public X class A public virtual X f return new X class B public A public virtual Y f return new Y zamishuyuchi metod mozhna povernuti utochnenij tip rezultatu V nastupnij tablici zibrana variantnist pri zamishenni metodiv dlya riznih mov programuvannya tip argumenta tip rezultatu C invariantnij invariantnij C z 1998 Java z J2SE 5 0 Scala D invariantnij kovariantnij kontravariantnij kovariantnij Eiffel kovariantnij kovariantnijVariantnist shablonnih tipivV deyakih movah programuvannya sho pidtrimuyut mozhlivo vkazati variantnist shablonnogo tipu po parametru Ce mozhlivo pri deklaraciyi shablonnogo tipu yak v C chi pri stvorenni vikoristanni konkretnogo tipu na osnovi shablonnogo yak v Java Zadannya variantnosti pri deklaraciyi v C ce mozhlivo tilki dlya interfejsiv klyuchovimi klovami out ta in v Scala ta OCaml klyuchovimi klovami ta Yaksho variantnist ne zadana to tip bude vvazhatis invariantnim Priklad interface IEnumerator lt out T gt T Current get bool MoveNext IEnumerator lt Cat gt bude vvazhatis uspadkovanim vid IEnumerator lt Animal gt Zadannya variantnosti pri vikoristanni Zadannya variantnosti pri stvorenni kozhnogo konkretnogo tipu ye bilsh gnuchkim Vono dozvolyaye avtoru klasa ne deklaruvati dekilka interfejsiv z riznoyu variantnistyu V Java variantnist zadayetsya razom iz zadannyam obmezhuyuchogo tipu List lt extends Animal gt bude kovariantnim tipu elementa List lt super Animal gt bude kontravariantnim tipu elementa Pri zadanni variantnosti bude zaboroneno vikoristovuvati metodi klasu z vidminnoyu variantnistyu Dzherelahttp msdn microsoft com ru ru library dd799517 aspx 24 Grudnya 2015 u Wayback Machine Kovariantnist i kontravariantnist v shablonah http blogs msdn com b ericlippert archive 2007 10 17 covariance and contravariance in c part two array covariance aspx Arhivovano 28 Chervnya 2013 u WebCite Covariance and Contravariance in C Part Two Eric Lippert Func lt T TResult gt Delegate 19 Serpnya 2017 u Wayback Machine MSDN Documentation