Example8.4

8.4 最下層の型 (Least Types)

Scala では、オブジェクトを型でパラメータ化することはできません。そういう訳で、たとえ任意の型の空スタックを表すただ一つの値で充分だったとしても、最初にジェネリッククラス EmptyStack[A] を定義しました。しかし、共変的スタックについては、次のイディオムを使えます。

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

ボトム型 Nothing は値を持ちません。したがって型 Stack[Nothing] は、EmptyStack が要素を含まないことを表現します。さらに、Nothing は他のすべての型のサブタイプです。ですから、共変的スタックではどんな型 T に対しても、Stack[Nothing] は Stack[T] のサブタイプです。これによってユーザーコード中で、単一の空スタックオブジェクトを使用できます。たとえば、

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

この式について、型の割り当てを詳細に解析しましょう。EmpthStack オブジェクトは型 Stack[Nothing] であり、次のメソッドを持っています。

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

局所的な型推論は、型パラメータ B は EmptyStack の適用において String へとインスタンス化されているに違いない、と決定します。したがって、その適用の結果型(戻り値型)は Stack[String] であり、次のメソッドを持っています。

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

上記の値定義の最後の箇所は、このメソッドの new AnyRef() への適用です。局所的型推論は今回、型パラメータ b は AnyRef へとインスタンス化されているに違いなく、結果型は Stack[AnyRef] である、と決定します。したがって値 s に割り当てられる型は Stack[AnyRef] です。

Nothing はすべての型のサブタイプでした。ほかに、型 Null というものもあり、これは scala.AnyRef と、AnyRefを継承するすべてのクラスのサブタイプです。 Scala の null リテラルはその型の唯一の値です。これによって null はすべての参照型と互換ですが、Int のような値型とは互換ではありません。

完全に改良したスタック定義で、この章を締めくくります。いまやスタックは共変的サブタイプで、push メソッドは一般化され、空スタックは単一のオブジェクトで表現されます。

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 
}

Scala ライブラリ内の多くのクラスはジェネリックです。ジェネリックなクラスの系統でよく使われる、タプルと関数を紹介します。他のよく使われるクラスであるリストは、次の章に回します。


名前:
コメント:

タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2011年02月24日 08:43
ツールボックス

下から選んでください:

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