Advantages of Scala's type system
I am exploring the Scala language. One claim I often hear is that Scala has a stronger type system than Java. By this I think what people mean is that:
scalac
rejects certain buggy programs whichjavac
will compile happily, only to cause a runtime error.- Certain invariants can be encoded in a Scala program such that the co开发者_如何学Gompiler won't let the programmer write code that violates the condition.
Am I right in thinking so?
The main advantage of the Scala Type system is not so much being stronger but rather being far richer (see "The Scala Type System").
(Java can define some of them, and implement others, but Scala has them built-in).
See also The Myth Makers 1: Scala's "Type Types", commenting Steve Yegge's blog post, where he "disses" Scala as "Frankenstein's Monster" because "there are type types, and type type types".
- Value type classes (useful for reasonably small data structures that have value semantics) used instead of primitives types (Int, Doubles, ...), with implicit conversion to "Rich" classes for additional methods.
- Nonnullable type
- Monad types
- Trait types (and the mixin composition that comes with it)
- Singleton object types (just define an 'object' and you have one),
- Compound types (intersections of object types, to express that the type of an object is a subtype of several other types),
- Functional types (
(type1, …)=>returnType
syntax), - Case classes (regular classes which export their constructor parameters and which provide a recursive decomposition mechanism via pattern matching),
- Path-dependent types (Languages that let you nest types provide ways to refer to those type paths),
- Anonymous types (for defining anonymous functions),
- Self types (can be used for instance in Trait),
- Type aliases, along with:
- package object (introduced in 2.8)
- Generic types (like Java), with a type parameter annotation mechanism to control the subtyping behavior of generic types,
- Covariant generic types: The annotation
+T
declares typeT
to be used only in covariant positions.Stack[T]
is a subtype ofStack[S]
ifT
is a subtype ofS
. - Contravariant generic types:
-T
would declareT
to be used only in contravariant positions.
- Covariant generic types: The annotation
- Bounded generic types (even though Java supports some part of it),
- Higher kinded types, which allow one to express more advanced type relationships than is possible with Java Generics,
- Abstract types (the alternative to generic type),
- Existential types (used in Scala like the Java wildcard type),
- Implicit types (see "The awesomeness of Scala is implicit",
- View bounded types, and
- Structural types, for specifing a type by specifying characteristics of the desired type (duck typing).
The main safety problem with Java relates to variance. Basically, a programmer can use incorrect variance declarations that may result in exceptions being thrown at run-time in Java, while Scala will not allow it.
In fact, the very fact that Java's Array
is co-variant is already a problem, since it allows incorrect code to be generated. For instance, as exemplified by sepp2k:
String[] strings = {"foo"};
Object[] objects = strings;
objects[0] = new Object();
Then, of course, there are raw types in Java, which allows all sort of things.
Also, though Scala has it as well, there's casting. Java API is rich in type casts, and there's no idiom like Scala's case x: X => // x is now safely cast
. Sure, one case use instanceof
to accomplish that, but there's no incentive to do it. In fact, Scala's asInstanceOf
is intentionally verbose.
These are the things that make Scala's type system stronger. It is also much richer, as VonC shows.
精彩评论