C#: Является различие (Ковариантность / Контравариантность) другим словом для Полиморфизма?

Для таблиц с contentInset установка смещения содержимого на CGPointZero не будет работать. Он будет прокручиваться до верхней части содержимого, а не до верхней части таблицы.

Принимая во внимание содержание содержимого, получается вместо этого:

[tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:NO];
41
задан Andreas Grech 3 July 2009 в 08:46
поделиться

5 ответов

Это определенно связано с полиморфизмом. Я бы не сказал, что они просто «другое слово» для обозначения полиморфизма - они об очень конкретных ситуациях, когда вы можете рассматривать один тип, как если бы это был другой тип в определенном контексте .

] Например, при нормальном полиморфизме вы можете рассматривать любую ссылку на Банан как ссылку на Fruit - но это не значит, что вы можете заменить Fruit каждый раз вы видите тип банан . Например, список List нельзя рассматривать как List , потому что list.Add (new Apple ()) действителен для Список <Фрукты> , но не для Список <Банана> .

Ковариация позволяет заменять «больший» (менее конкретный) тип в API, где исходный тип используется только в позиции «вывода» (например, как возвращаемое значение). Контравариантность позволяет заменять «меньший» (более конкретный) тип в API, где исходный тип используется только в позиции «ввода».

Трудно вдаваться во все детали в одно сообщение SO (хотя, надеюсь, кто-то другой сделает лучше, чем это!). У Эрика Липперта есть отличная серия сообщений в блоге об этом.

(более конкретный) тип, который должен быть заменен в API, где исходный тип только используется в позиции «ввода».

Трудно вдаваться во все детали в одном сообщении SO (хотя, надеюсь, кто-то другой сделает работу лучше, чем эта!). У Эрика Липперта есть отличная серия сообщений в блоге об этом.

(более конкретный) тип, который должен быть заменен в API, где исходный тип только используется в позиции «ввода».

Трудно вдаваться во все детали в одном сообщении SO (хотя, надеюсь, кто-то другой сделает работу лучше, чем эта!). У Эрика Липперта есть отличная серия сообщений в блоге об этом.

67
ответ дан 27 November 2019 в 00:08
поделиться

Спасибо за все приветствия, ребята.

Ответы Джона и Расмуса прекрасны, я бы просто добавил небольшое техническое примечание.

Если говорить небрежно и неформально, да, люди используют термины «ковариация» и «контравариантность» для обозначения определенного вида полиморфизма. То есть вид полиморфизма, при котором вы относитесь к последовательности пауков, как если бы это была последовательность животных.

Если бы мы полностью овладели компьютерными науками и попытались дать более технические определения, я бы, вероятно, не сказал, что ковариация и контравариантность являются «своего рода полиморфизмом». Я бы подошел к более техническому определению, например так:

Во-первых, я хотел бы отметить, что в C # есть два возможных типа полиморфизма, о которых вы, возможно, говорите, и важно не путать их.

Первый тип традиционно называется «специальный полиморфизм», и это полиморфизм, в котором у вас есть метод M (Animal x), и вы передаете ему пауков, жирафов и валлаби, и метод единообразно обрабатывает его переданные аргументы аналогичным образом, используя общие черты, гарантированные базовым классом Animal.

Второй тип традиционно называется «параметрическим полиморфизмом» или «универсальным полиморфизмом». Это возможность создать общий метод M (T t) , а затем иметь кучу кода в методе, который снова обрабатывает аргумент единообразно на основе общностей, гарантированных ограничениями на T.

Я думаю, вы говорите о первом виде полиморфизма. Но я хочу сказать, что мы можем определить полиморфизм как способность языка программирования одинаково относиться к различным вещам на основе известной общности. (Например, известный базовый тип или известный реализованный интерфейс.)

Ковариация и контравариантность - это способность языка программирования использовать преимущества общих черт между универсальными типами, выведенных из известных общих черт их аргументов типа.

]
44
ответ дан 27 November 2019 в 00:08
поделиться

Вы можете подумать о ко- и контравариантности как о продвинутой форме полиморфизма. Вы можете не только использовать дочерний класс, как если бы он был его родительским классом, с ко- и контравариантностью, полиморфизм распространяется на классы, которые относятся к полиморфным классам.

Представьте себе два класса:

public class Pet { /*...*/ }
public class Cat:Pet { /*...*/ }

Полиморфизм способен использовать Cat в качестве Pet :

void Feed(Pet pet) { /* ... */ }

Cat cat = ...
Feed(cat);

Ко- и контравариантность используется, чтобы говорить о возможности использования ICollection в качестве ICollection (ковариация):

void FeedAll(ICollection<Pet> pets) { /* ... */ }

List<Cat> cats = ...
FeedAll(cats);

или использовать Action как Action (контравариантность):

Action<Pet> GetFeeder() { /* ... */ }

Action<Cat> feeder = GetFeeder();

Эрик Липперт написал об этом отличную серию блогов, когда они впервые разрабатывали эту функцию. Часть первая здесь .

18
ответ дан 27 November 2019 в 00:08
поделиться

Я думаю, что это особый вид полиморфизма, а не иначе. Это полиморфизм в делегатах , где делегат с возвращаемым типом base может принимать дочерний тип.

-2
ответ дан 27 November 2019 в 00:08
поделиться

Думаю, это зависит от того, как вы используете Qt. Если вы используете его во всем своем продукте, вероятно, имеет смысл использовать контейнеры Qt. Если вы используете его только (например) для части пользовательского интерфейса, возможно, лучше использовать стандартные контейнеры C ++.

Критические изменения

Ковариация и контравариантность в C #, часть десятая: работа с неоднозначностью

Ковариация и контравариантность, часть одиннадцатая: до бесконечности, но не дальше

13
ответ дан 27 November 2019 в 00:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: