Scala 类型系统的优点
Posted
技术标签:
【中文标题】Scala 类型系统的优点【英文标题】:Advantages of Scala's type system 【发布时间】:2011-03-07 23:08:25 【问题描述】:我正在探索 Scala 语言。我经常听到的一种说法是 Scala 具有比 Java 更更强大的类型系统。我认为人们的意思是:
scalac
拒绝某些错误程序,javac
会顺利编译,但只会导致运行时错误。
可以在 Scala 程序中对某些不变量进行编码,这样编译器就不会让程序员编写违反条件的代码。
我这样想对吗?
【问题讨论】:
Java 不会像 Scala 那样让你编译“有缺陷的程序”;然而,与 Java 相比,Scala 允许 [安全地] 表达更多的结构——而且通常以一种更简单的方法。不过,Scala 仍然“遭受”类型擦除。 @pst:是的,它会的。String[] strings = "foo"; Object[] objects = strings; objects[0] = new Object();
将在 java 中编译得很好,然后在运行时抛出 NPE。等效的 scala 代码不会编译。
@sepp2k 我认为被抛出的是ArrayStoreException
,而不是NPE。
@pst:我认为拥有静态类型系统的全部意义在于自动派生程序的某些属性,而无需实际运行它。所以我期待scalac
分析输入程序并仅在不存在某些类别的错误时接受它。
是的,当然。我不知道我为什么说 NPE。
【参考方案1】:
Scala 类型系统的主要优点不是更强,而是更丰富(请参阅“The Scala Type System”)。 (Java 可以定义其中的一些,并实现其他的,但 Scala 内置了它们)。 另请参阅 The Myth Makers 1: Scala's "Type Types",评论 Steve Yegge's blog post,他将 Scala 视为“弗兰肯斯坦的怪物”,因为“存在类型类型和类型类型”。
使用值类型类(对于具有值语义的相当小的数据结构很有用)代替原始类型(Int、Doubles、...),并隐式转换为“Rich”类以获取其他方法。 Nonnullable type Monad types 特征类型(以及附带的mixin composition) 单例对象类型(只需定义一个“对象”即可), Compound types(对象类型的交集,表示一个对象的类型是其他几种类型的子类型), Functional types((type1, …)=>returnType
语法),
Case classes(导出其构造函数参数并通过模式匹配提供递归分解机制的常规类),
Path-dependent types(允许嵌套类型的语言提供了引用这些类型路径的方法),
Anonymous types(用于定义匿名函数),
Self types(可以是used for instance in Trait),
Type aliases,以及:
package object(2.8 引入)
Generic types(类似于 Java),带有 type parameter annotation mechanism 来控制泛型类型的子类型化行为,
协变泛型类型:注释+T
声明类型T
仅用于协变位置。如果T
是S
的子类型,则Stack[T]
是Stack[S]
的子类型。
逆变泛型类型:-T
将声明 T
仅用于逆变位置。
有界泛型类型(即使Java supports some part of it),
Higher kinded types,它允许表达比 Java 泛型更高级的类型关系,
Abstract types(泛型的替代品),
Existential types(像 Java 通配符类型一样使用 in Scala),
Implicit types(见“The awesomeness of Scala is implicit”,
View bounded types,和
Structural types,用于通过指定所需类型的特征(鸭子类型)来指定类型。
【讨论】:
感谢您的详细记录。我会阅读链接的文章以获得更好的理解。 自我注意:另见我的旧答案***.com/questions/2682673/… 自我注意:由于隐式和新的 2.8 上下文绑定,“类型类”之类的模式很容易定义和使用:dcsobral.blogspot.com/2010/06/… 自我注意:当心与“拉皮条我的图书馆”模式一起使用的结构类型:可能会出现严重的性能问题。见scala-notes.org/2010/06/… 我大胆地开始认为这是一个社区 wiki 页面(应该是!)并添加了更高种类的类型。【参考方案2】:Java 的主要安全问题与差异有关。基本上,程序员可以使用不正确的方差声明,这可能会导致 Java 在运行时抛出异常,而 Scala 不允许这样做。
事实上,Java 的Array
是协变的这一事实本身就是一个问题,因为它允许生成不正确的代码。比如sepp2k:
String[] strings = "foo";
Object[] objects = strings;
objects[0] = new Object();
当然,Java 中有原始类型,它允许各种事情。
此外,虽然 Scala 也有它,但还有强制转换。 Java API 有丰富的类型转换,没有像 Scala 的 case x: X => // x is now safely cast
这样的习语。当然,有一个案例使用instanceof
来完成此操作,但没有动力这样做。事实上,Scala 的asInstanceOf
是故意冗长的。
这些是让 Scala 的类型系统更强大的东西。它也更加丰富,正如VonC 所示。
【讨论】:
最后,一个比我的“更一般”列表更“主题”的答案;)+1 您准确地回答了原始问题,但 VonC 详细回答了一个略有不同的问题。我将他的答案投票为正确的答案,但您的回答也很受欢迎。希望您不介意错过声誉积分。 @binil 一点也不。 VonC 的回答很棒,即使他真的不需要额外的声誉...... ;-)以上是关于Scala 类型系统的优点的主要内容,如果未能解决你的问题,请参考以下文章
每日一题Scala类型系统中 NullNothingNilNoneUnit 的区别
scala类型系统:24) 理解 higher-kinded-type