Tour of Scala

ジェネリッククラス

Language

ジェネリッククラスはパラメータとして型を1つ受け取るクラスです。それらはコレクションクラスで特に役立ちます。

ジェネリッククラスの定義

ジェネリッククラスは角カッコ[]の中にパラメータとして型を1つ受け取ります。 型パラメータの識別子として文字Aを使う習慣がありますが、任意のパラメータ名を使うことができます。

class Stack[A] { private var elements: List[A] = Nil def push(x: A): Unit = elements = x :: elements def peek: A = elements.head def pop(): A = { val currentTop = peek elements = elements.tail currentTop } } 

このStackクラスの実装はパラメータとして任意の型Aを受け取ります。 これはメンバーのリストvar elements: List[A] = Nilが型Aの要素のみを格納できることを意味します。 手続きdef pushは型Aのオブジェクトのみを受け取ります (注: elements = x :: elementsは、xを現在のelementsの先頭に追加した新しいリストをelementsに割り当て直します)。

ここで Nil は空の List であり、 null と混同してはいけません。

使い方

ジェネリッククラスを使うには、角カッコの中にAの代わりに型を入れます。

val stack = new Stack[Int] stack.push(1) stack.push(2) println(stack.pop) // prints 2 println(stack.pop) // prints 1 

インスタンスstackはIntのみを受け取ることができます。 しかしながら、型がサブタイプを持つ場合、それらは以下のように渡すことができます。

class Fruit class Apple extends Fruit class Banana extends Fruit val stack = new Stack[Fruit] val apple = new Apple val banana = new Banana stack.push(apple) stack.push(banana) 

クラスAppleBananaは共にFruitを継承しています。そのためFruitのスタックにはapplebananaのインスタンスを追加できます。

注意: ジェネリック型のサブタイプは*非変(invariant)*です。つまりStack[Char]型の文字スタックがあるとき、それをStack[Int]型の整数スタックとして使うことはできません。文字スタックに整数を入れることはできるので、このことは変に思えるかもしれません。結論としては、B = Aの場合に限り、Stack[A]Stack[B]の唯一のサブタイプとなります。これでは制限が強いので、ジェネリック型のサブタイプの振る舞いをコントロールするために、Scalaは型引数アノテーションの仕組みを提供します。

Contributors to this page: