我只想回答声明站点和使用站点之间的差异,因为尽管C#和Java泛型在许多其他方面有所不同,但这些差异大多与方差正交。
首先,如果我没记错的话,使用场所方差严格比声明场所方差(尽管以简洁为代价)更强大,或者至少Java的通配符(实际上比使用场所方差更强大)。这种增强的功能对于大量使用状态构造的语言(例如C#和Java)特别有用(但Scala则少得多,特别是因为其标准列表是不可变的)。考虑
List<E>(或
IList<E>)。由于它具有添加E和获取E的方法,因此它相对于E是不变的,因此无法使用声明位置的方差。但是,对于使用场所方差,您只能说
List<+Number>获得的协变子集
List和
List<-Number>以获得的协变子集。
List。在声明站点语言中,库的设计者必须为每个子集创建单独的接口(或类,如果允许类的多重继承),并
List扩展这些接口。如果库设计人员不执行此 *** 作(请注意,C#
IEnumerable仅处理的协变部分的一小部分
IList),那么您就不走运了,并且不得不诉诸于使用某种语言时遇到的相同麻烦差异。
因此,这就是使用站点继承相对于声明站点继承的优势。对于用户而言,声明站点继承相对于使用站点继承的优势基本上是简洁的(前提是设计人员已努力将每个类/接口分为其协变和反协变量部分)。对于类似
IEnumerable或的东西
Iterator,最好不必每次使用该接口时都指定协方差。Java通过使用冗长的语法(特别是Java的解决方案最理想的双变量)使这一点特别烦人。
当然,这两种语言功能可以共存。对于自然协变或相反的类型参数(例如
IEnumerable/
Iterator),请在声明中声明。对于自然不变的类型参数(例如中的in
(I)List),请在每次使用时声明要使用哪种类型的变数。只是不要为带有声明位置差异的参数指定使用位置差异,因为这会使事情变得混乱。
我还没有涉及其他更详细的问题(例如,通配符实际上比使用站点差异更强大),但是我希望这可以回答您对内容的问题。我承认我偏向使用场所差异,但是我试图描绘在与程序员和语言研究人员的讨论中都体现出的两者的主要优势。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)