0

In one of the Stack Overflow answers it is quoted that:

Scala is a fully object oriented language, more so than Java, with one of the most advanced type systems available on non-research languages.

In what ways is Scala's type system more advanced than Java's?

Somasundaram Sekar
  • 5,244
  • 6
  • 43
  • 85
  • 3
    I'm sorry but just saw a question that asks SO users to compare groovy scala and clojure and has 500+ up votes. I accept the question is broad but I don't want it to be branded unfit for SO – Somasundaram Sekar Oct 18 '14 at 13:53
  • Thanks for down voting anyway – Somasundaram Sekar Oct 18 '14 at 13:55
  • 2
    Scala's type system features—among others—variance annotations, path-dependent types, higher-kinded types, proper existential types, structural types, abstract types and singleton types. Java doesn't have any of these. –  Oct 18 '14 at 14:06
  • 1
    Well to add more context im learning Scala, so the question was broad but you sir rightfold now have given me a check list to follow, thanks a ton – Somasundaram Sekar Oct 18 '14 at 14:10
  • just because there are 500+ people that *like* something in no way qualifies it as *on topic*, unfortunately it just means there are 500+ people that don't know or choose to ignore the rules of the site. –  Oct 18 '14 at 14:22
  • 4
    I think this is a perfectly fine question. It's objective, reasonably specific and fits the philosophy of the site: a database of programming-related knowledge in Q&A form. That the answer is longer than two paragraphs doesn't make it any less fitting. –  Oct 18 '14 at 14:31

1 Answers1

12

Scala's type system can do pretty much everything Java's can (with some warts removed, like covariant arrays). In addition, it has the following features:

Variance annotations

An abstract class C that is generic on T can be made a subtype of C[U] where U is a subtype or a supertype of T.

class C[+T] // C[T] <: C[U] iff T <: U
class D[-T] // C[T] <: C[U] iff U <: T

This is incredibly useful when passing around immutable data structures parameterised on the type of values they contain. For example, List[String] is a subtype of List[Any].

Java uses wildcards for this, thereby moving taking care of this to the user of the API rather than the definer. This is suboptimal in many cases.

Path-dependent types

In Java, a value of non-static inner class type stores a pointer to the object of the containing class type. In Scala this is also the case, except it also works this way in the type system. For example:

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

Java lacks this feature; x and y both have type P.C.

Higher-kinded types

A type cannot only be parameterised on another type but also on a type constructor:

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

This is most useful in type classes like Functor and Monad.

Java lacks this feature.

Structural types

A type is a subtype of a structural type if it contains all members of the structural type.

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

class A { def x = "a"; def y = 1 }
class B { def y = 1 }

Here, A is a subtype of S because it defines both def x: String and def y: Int which are required by S. B is not a subtype of S because B does not define def y: Int. Note that in many cases, reflection is used when accessing members of values of which the static type is a structural type, and therefore structural typing is often discouraged.

They can be used to simulate type lambdas, though, without runtime cost.

Java lacks this feature, and it's arguably not very useful anyway.

Abstract types

Like methods, types can be abstract:

trait T {
  type G
  def f: G
}

class C extends T {
  override type G = Int
  override def f = 42
}

Java lacks this feature.

Singleton types

The singleton type of x contains x and only x. This can be useful in particular when one wants to guarantee that a method returns 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

In Java this isn't possible; you either have to parameterise T and rely on CRTP, or have x return T instead of C.

Bottom type

Scala has the bottom type Nothing that is a subtype of all types and contains no values. This is the type of throw expressions and the return type of functions that never return (i.e. always throw an exception or enter an infinite loop).

Java lacks this feature and uses void instead. Scala has no void but makes the distinction between functions that return no value and non-returning functions explicit.

Community
  • 1
  • 1