View on GitHub

blog

Ко/Контр вариантность

sample

В язке Java есть несколько типов данных, рассмотрим следующие

На картинке отображены 8 переменных:

Операция присвоения

В основе правил присваения следующее:

Для переменной x типа X, можно присвоить значение типа X или дочернего типа данных X

т.е. для переменной n1 допустимы операции:

n1 = n2 // т.е. number тип полностью совметим с самим с собой (number)

n1 = i1 // т.е. int расширяет number, 
n1 = i2 // и все операции над number доступны и для int

n1 = d1 // т.е. double расширяет number, 
n1 = d2 // и все операции над number доступны и для double

И не допустипы операции:

n1 = o1 // т.к. object не является number
n1 = o2 //    и object не является дочерним к number

Так же для переменной o1,o2 доступны любые операции присвоения, среди указанных, а для d1,d2 доступны только операции присвоения для типов double

Отношения операции присвоения

Можно обобщить операции присвоения и построить возможные отношения между типами данных в аспекте операции присвоения.

Рассмотри в общем:

left операция(=) right
Left Right в коде Отновшение left к right
Left = Right Right = Left   Инвариантность (inv)
Left - родитель к Right Right - дочерний к Left class Right extends Left left ко-вариантен к right (cov)
Left - дочерний к Right Right - родитель к Left class Left extends Right left контр-вариантен к right (ctr)
Left нет пересечений с Right Right нет пересечений с Left   нет вариантов (no)

Расширеный пример присвоения

В разрвнх языках, где есть lambda, поддерживается переменные которые могут указывать на функции.

Для примера (Java 8+):

BiFunction<Integer,Integer,Number> f1 = (a,b) -> a+b;
BiFunction<Number,Number,Integer> f2 = ...;

Теперь код вызова

Number n1 = f1( 10, 12 )
Number n2 = f2( 10, 12 )

С точки зрения компилятора код выше возвращает один и тот же тип данных, т.к. вызов f2, хоть и возвращает Integer, но Integer является так же Number - т.е. результат вызова f2 ко-вариантен к f1

Аргументы вызова вступают в противоположное отношения:

Integer a1 = 10
Integer a2 = 12

Number n1 = f1( a1, a2 )
Number n2 = f2( a1, a2 )

Сами переменные-функции f1, f2 тоже относяться в отношении: