Является ли вложенная CoVariance становится Contravariance? - PullRequest
0 голосов
/ 18 декабря 2018

Понятия CoVariance и CotraVariance я понимал так: когда интерфейс необходимо пометить как только для чтения , тогда мы используем из T и для только для записи интерфейс, который мы используем в T , чтобы обеспечить безопасность типов при получении и настройке объектов.Но когда мы вкладываем их, как ContraVariance рассматривается как CoVariance.Например:

interface IObservable<out T>
{
    IDisposable Subscribe(IObserver<T> o);
}
interface IObserver<in T>
{
    void OnNext(T t);

    void OnError(Exception e);

    void OnCompleted();
}

Пожалуйста, объясните на примере, как вложенные вещи изменяют свою дисперсию.или, пожалуйста, перенаправьте меня на хороший материал для чтения.Заранее спасибо.

1 Ответ

0 голосов
/ 18 декабря 2018

Давайте напишем (модифицированный вид символа «меньше») для отношения «есть», которое мы имеем для ссылочных типов.Например, Elephant ⊂ IMammal, или IMammal ⊂ IAnimal.

Сначала посмотрите на IObserver<>:

interface IObserver<in T>
{
    void OnNext(T t);
    // other members irrelevant
}

«В» означает, что оно противоречиво.Контравариантное означает:

Если X ⊂ Y, то IObserver<Y> ⊂ IObserver<X>.

Противоположность заключается в том, что порядок X и Y изменяется, когда выприменить IObserver<·> с обеих сторон ".Это похоже на умножение неравенства (по математике) на отрицательное число с обеих сторон.Вы должны поменять обе стороны неравенства (или превратить в ).

Причина, по которой разрешено иметь IObserver<T> контравариант в T, заключается в том, что T используется только для параметра-значения в методе (а именно OnNext).

Предположим, у нас есть экземпляр IObserver<IMammal>.Это может занять любой IMammal в его OnNext(IMammal t) методе.Может ли этот экземпляр действовать как IObserver<Elephant>?Да, потому что, если он может принимать любой IMmammal, то, в частности, он может принимать Elephant, и поэтому контрвариант является целым и невредимым.Поскольку Elephant "представляет собой" IMammal, то IObserver<IMammal> "представляет собой" IObserver<Elephant>.

Противопоставление меняет соотношение.

Теперь давайте посмотрим на другоетипа (и теперь мы подходим к тому, что вы просите!).Я переименую его с IObservable<> на IVable<>:

interface IVable<out T>
{
    IDisposable Subscribe(IObserver<T> o);
}

«Out» означает ковариантный.Ковариант означает:

Если X ⊂ Y, то IVable<X> ⊂ IVable<Y>.

Это как в математике, когда вы умножаете обе стороны неравенства на положительное номер.X и Y являются , а не заменяемыми (совместно).

Но как может IVable<T> быть ковариантным, когда у него есть метод, Subscribe, который принимает "что-то с T "?Это потому, что это «что-то» является контравариантным в T!

Посмотрим, будет ли оно в целости и сохранности.Итак, предположим, у нас есть экземпляр, который IVable<IMammal>.Это означает, что у него есть Subscribe, который может принимать любой IObserver<IMammal>.Но последнее является контравариантным, поэтому, поскольку IMammal "является" IAnimal, то любое IObserver<IAnimal> "является" IObserver<IMammal>.Итак, это показывает нам, что наш IVable<IMammal> может действовать как IVable<IAnimal>, как указано ковариацией.Так что все хорошо.

В заключение: принятие "во" чего-то, что противоречиво в T, действует как "вне" в T.Точно так же, посылая «из» что-то, что является контравариантным в T, действуйте как «в» в T.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...