And*_*ech 41 c# polymorphism covariance contravariance variance
我试图弄清楚这些词的确切含义,Covariance以及Contravariance在线的几篇文章和关于StackOverflow的问题,从我能理解的,它只是多态的另一个词.
我对上述陈述是否正确?或者我弄错了?
Jon*_*eet 67
它肯定与多态性有关.我不会说它们只是多态性的"另一个词" - 它们是关于非常具体的情况,你可以将一种类型视为某种情况下的另一种类型.
例如,对于正常的多态性,您可以将对a的任何引用Banana视为对a的引用Fruit- 但这并不意味着Fruit 每次看到该类型时都可以替换Banana.例如,a List<Banana>不能被视为List<Fruit>因为list.Add(new Apple())有效List<Fruit>但不适用List<Banana>.
协方差允许在API中替换"更大"(更不具体)类型,其中原始类型仅用于"输出"位置(例如,作为返回值).逆变量允许在API中替换"较小"(更具体)类型,其中原始类型仅用于"输入"位置.
在一篇SO帖子中很难详细介绍所有细节(尽管希望其他人能比这更好!).Eric Lippert有一系列关于它的博客文章.
Eri*_*ert 44
感谢所有的呐喊,伙计们.
Jon和Rasmus的答案很好,我只想添加一个快速的技术说明.
随便和非正式地说,是的,人们使用"协方差"和"逆变"来指代特定类型的多态性.也就是说,你将一系列蜘蛛视为一系列动物的多态性.
如果我们得到所有的计算机技术并尝试制定更多的技术定义,那么我可能不会说协方差和逆变是"一种多态".我会接近这样一个更技术性的定义:
首先,我注意到你可能正在谈论的C#中有两种可能的多态性,重要的是不要混淆它们.
第一种传统上称为"ad hoc多态性",这就是你有一个方法M(Animal x)的多态性,你将蜘蛛,长颈鹿和小袋鼠传给它,并且该方法统一处理它的传入参数通过使用Animal基类保证的共性来实现.
第二种传统上称为"参数多态"或"通用多态".这是制作泛型方法的能力M<T>(T t),然后在方法中有一堆代码,再次根据T上的约束保证的共性统一处理参数.
我想你在谈论第一种多态性.但我的观点是,我们可以将多态定义为编程语言根据已知的通用性统一处理不同事物的能力.(例如,已知的基本类型或已知的已实现接口.)
协方差和逆变是编程语言利用从其类型参数的已知共性推导出的泛型类型之间的共性的能力.
Ras*_*ber 18
您可以将共变和逆变视为多态的高级形式.您不仅可以使用子类,就像它的父类一样,具有协方差和逆变性,多态性扩展到与多态类相关的类.
想象两个类:
public class Pet { /*...*/ }
public class Cat:Pet { /*...*/ }
Run Code Online (Sandbox Code Playgroud)
多态性能够使用a Cat作为Pet:
void Feed(Pet pet) { /* ... */ }
Cat cat = ...
Feed(cat);
Run Code Online (Sandbox Code Playgroud)
协变量和逆变量用于讨论能够使用a ICollection<Cat>作为ICollection<Pet>(协方差):
void FeedAll(ICollection<Pet> pets) { /* ... */ }
List<Cat> cats = ...
FeedAll(cats);
Run Code Online (Sandbox Code Playgroud)
或者Action<Pet>用作Action<Cat>(逆变):
Action<Pet> GetFeeder() { /* ... */ }
Action<Cat> feeder = GetFeeder();
Run Code Online (Sandbox Code Playgroud)
Eric Lippert在他们第一次设计这个功能时写了一篇很棒的博客系列.第一部分在这里.