Scala的类型系统与Java相比如何?

Som*_*kar 0 java type-systems scala

在其中一个Stack Overflow答案中,引用了:

Scala是一种完全面向对象的语言,比Java更为强大,它是非研究语言中最先进的类型系统之一.

Scala的类型系统在哪些方面比Java更先进?

rig*_*old 10

Scala的类型系统可以完成Java所能做的一切(删除一些疣,如协变数组).此外,它还具有以下功能:

方差注释

一个抽象类C是一般上T可制成的子类型C[U],其中U是一个亚型或的超类型T.

class C[+T] // C[T] <: C[U] iff T <: U
class D[-T] // C[T] <: C[U] iff U <: T
Run Code Online (Sandbox Code Playgroud)

当传递对它们包含的值类型进行参数化的不可变数据结构时,这非常有用.例如,List[String]是一个子类型List[Any].

Java为此使用通配符,从而将这种方式转移给API的用户而不是定义者.在许多情况下,这是次优的.

路径依赖类型

在Java中,非静态内部类类型的值存储指向包含类类型的对象的指针.在Scala中也是如此,除了它在类型系统中也以这种方式工作.例如:

class P {
  class C { }
}

val x = new P
val y = new P
var z = new x.C
z = new y.C // type error; x.C and y.C are distinct types
Run Code Online (Sandbox Code Playgroud)

Java缺乏此功能; x并且y都有型P.C.

高级类型

类型不仅可以在另一种类型上进行参数化,还可以在类型构造函数上进行参数化:

trait Functor[F[_]] {
  def map[T, U](function: T => U)(functor: F[T]): F[U]
}
Run Code Online (Sandbox Code Playgroud)

这在像Functor和这样的类型类中最有用Monad.

Java缺乏此功能.

结构类型

如果类型包含结构类型的所有成员,则类型是结构类型的子类型.

type S = { def x: String; def y: Int }

class A { def x = "a"; def y = 1 }
class B { def y = 1 }
Run Code Online (Sandbox Code Playgroud)

这里A是一个子类型,S因为它定义了两者def x: Stringdef y: Int哪些是必需的S.B不是S因为B没有定义的子类型def y: Int.请注意,在许多情况下,在访问静态类型为结构类型的值的成员时使用反射,因此通常不鼓励进行结构类型化.

但是,它们可用于模拟lambda类型,而无需运行时成本.

Java缺乏此功能,无论如何它可能都不是很有用.

抽象类型

与方法类似,类型可以是抽象的:

trait T {
  type G
  def f: G
}

class C extends T {
  override type G = Int
  override def f = 42
}
Run Code Online (Sandbox Code Playgroud)

Java缺乏此功能.

单身人士类型

单例类型x包含x且仅包含x.当一个人想要保证方法返回时,这可能很有用this:

trait T {
  def x: this.type
}

class C extends T {
  def x = this
}

val x: T = new C
x.x // has type x.type (which is a subtype of C), not type T
Run Code Online (Sandbox Code Playgroud)

在Java中,这是不可能的; 您要么必须参数化T并依赖CRTP,要么x返回T而不是C.

底部类型

Scala的底部类型Nothing是所有类型的子类型,不包含任何值.这是throw表达式的类型和永不返回的函数的返回类型(即总是抛出异常或进入无限循环).

Java缺少此功能void而是使用.Scala没有,void但区分了不返回值的函数和非返回函数的显式.