Example8.4

「Example8.4」の編集履歴(バックアップ)一覧に戻る

Example8.4 - (2008/06/17 (火) 23:04:36) のソース

** 8.4 Least Types

Scala does not allow one to parameterize objects with types. That’s why we originally defined a generic class EmptyStack[A], even though a single value denoting empty stacks of arbitrary type would do. For co-variant stacks, however, one can use the following idiom: 

 object EmptyStack extends Stack[Nothing] { ... } 

The bottom type Nothing contains no value, so the type Stack[Nothing] expresses the fact that an EmptyStack contains no elements. Furthermore, Nothing is a subtype of all other types. Hence, for co-variant stacks, Stack[Nothing] is a subtype of Stack[T], for any other type T. This makes it possible to use a single empty stack object in user code. For instance:

 val s = EmptyStack.push("abc").push(new AnyRef()) 

Let’s analyze the type assignment for this expression in detail. The EmptyStack object is of type Stack[Nothing], which has a method 

 push[B >: Nothing](elem: B): Stack[B] . 

Local type inference will determine that the type parameter B should be instantiated to String in the application EmptyStack.push("abc"). The result type of that application is hence Stack[String], which in turn has a method 

 push[B >: String](elem: B): Stack[B] . 

The final part of the value definition above is the application of this method to new AnyRef(). Local type inference will determine that the type parameter b should this time be instantiated to AnyRef, with result type Stack[AnyRef]. Hence, the type assigned to value s is Stack[AnyRef]. 

Besides Nothing, which is a subtype of every other type, there is also the type Null, which is a subtype of scala.AnyRef, and every class derived from it. The null literal in Scala is the only value of that type. This makes null compatible with every reference type, but not with a value type such as Int. 

We conclude this section with the complete improved definition of stacks. Stacks have now co-variant subtyping, the push method has been generalized, and the empty stack is represented by a single object. 

 abstract class Stack[+A] { 
   def push[B >: A](x: B): Stack[B] = new NonEmptyStack(x, this) 
   def isEmpty: Boolean 
   def top: A 
   def pop: Stack[A] 
 } 
 object EmptyStack extends Stack[Nothing] { 
   def isEmpty = true 
   def top = error("EmptyStack.top") 
   def pop = error("EmptyStack.pop") 
 } 
 class NonEmptyStack[+A](elem: A, rest: Stack[A]) extends Stack[A] { 
   def isEmpty = false 
   def top = elem 
   def pop = rest 
 }

Many classes in the Scala library are generic. We now present two commonly used families of generic classes, tuples and functions. The discussion of another common class, lists, is deferred to the next chapter.
----
#comment
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。