1
38
我只想回答声明site和use site variance之间的区别,因为虽然C和Java泛型在许多其他方面有所不同,但这些区别大多与variance正交。
首先,如果我记得正确的话,使用site variance比声明site variance更强大(尽管代价是简洁),或者至少Java的通配符是(实际上比使用site variance更强大)。这种增强的功能对于大量使用有状态结构的语言(如C#和Java)尤其有用(但Scala的作用要小得多,特别是因为它的标准列表是不可变的)。考虑
这就是使用站点继承比声明站点继承的优势。声明站点继承比使用站点继承的优势基本上是为用户简化的(前提是设计人员经过努力将每个类/接口分离为其协变和逆变部分)。比如说
当然,这两种语言特征可以共存。对于自然协变或反变的类型参数(例如
还有一些更详细的问题我还没有涉及(例如通配符实际上比使用站点差异更强大),但我希望这能回答你的问题,你的内容。我承认我倾向于使用站点差异,但我试图描述在我与程序员和语言研究人员的讨论中出现的这两种方法的主要优点。 |
2
16
大多数人似乎更喜欢声明站点差异,因为它使 用户 对于库(虽然对库开发人员来说有点困难,但我认为库开发人员必须考虑差异,而不管差异实际写在哪里) 但是请记住,Java和C都不是好的语言设计的例子。 当 爪哇 由于Java5和类型擦除中兼容的虚拟机改进,使得方差正确并独立于JVM工作,使用站点方差使使用变得有点麻烦,类型擦除的特殊实现受到了应有的批评。 C类# 声明站点差异的模型减轻了库用户的负担,但是在他们引入具体化泛型的过程中,他们基本上在虚拟机中构建了差异规则。 即使在今天,他们也不能完全支持co-/contransage,因为这个错误(而不向后兼容的具体化集合类的引入将程序员分成了两个阵营)。 这对以CLR为目标的所有语言都构成了一个困难的限制,这也是为什么替代编程语言在JVM上更加活跃的原因之一,尽管看起来CLR具有“更好的特性”。 让我们看看 斯卡拉 :Scala是一个在JVM上运行的完全面向对象、功能性的混合体。 它们使用类似Java的类型擦除,但是泛型和(声明站点)差异的实现都比Java(或C#)更容易理解,更直接和强大,因为VM没有对差异的工作方式强加规则。Scala编译器检查方差符号,并可以拒绝不健全的源代码 编译时 而不是在运行时抛出异常,而生成的.class文件可以从Java无缝地使用。 声明站点方差的一个缺点是,在某些情况下,它似乎使类型推断变得更困难。
同时,Scala可以使用原始类型,而不必使用C语言中的集合来装箱它们。
Scala还可以通过使用清单“几乎”具体化泛型,清单允许它们在运行时检索泛型类型,就像在C#中那样。 |
3
1
Java风格泛型的缺点 一个结果是java版本只处理引用类型(或装箱值类型),而不处理值类型。IMO这是最大的缺点,因为它在许多场景中阻止了高性能泛型,并且需要手动编写特殊类型。 它不能保证像“这个列表只包含x类型的对象”这样的不变量,并且需要在每个getter上进行运行时检查。泛型类型确实存在。 使用反射时,不能询问泛型对象的实例它具有哪些泛型参数。 Java风格泛型的优势 您可以得到不同泛型参数之间的差异/可以转换。 |
4
0
Java:从Java 5开始使用site variance泛型。从1.0开始使用不同语法的已断开的协变数组。没有泛型的运行时类型信息。 C#:从C#2.0开始使用站点差异泛型。在C#4.0中添加了申报地点差异。从1.0开始使用不同语法的已断开的协变数组(与Java问题相同)。”“具体化”泛型意味着类型信息不会在编译时丢失。 Scala:这两种语言都使用自早期版本(至少自2008年以来)以来的站点/声明站点差异。数组不是一个单独的语言特性,因此使用相同的泛型语法和类型差异规则。某些集合是在VM级别使用JVM数组实现的,因此与Java代码相比,您可以获得同等或更好的运行时性能。 要详细说明C#/Java数组类型安全问题:可以将Dog[]强制转换为Pet[],然后添加C a t并触发编译时未捕获的运行时错误。Scala正确地实现了这一点。 |
Robert King · Unity C#语法问题-转换位置 1 年前 |
JBryanB · 如何从基本抽象类访问类属性 1 年前 |
law · 检查答案按钮的输入字符串格式不正确 2 年前 |
i_sniff_ket · 在unity之外使用unity类 2 年前 |