takafumi blog

日々の勉強メモ

【Scala】 変位パラメータの境界「下限境界」「上限境界」

環境   Scala 2.11.6 CentOS7.0

Scalaスケーラブルプログラミング」(コップ本)メモ

■ 下限境界、上限境界(第19章)

簡単にいうと、型パラメーターに制限をつける機能

▽下限境界 型パラメータが、どのサブクラスまで許可されるかを示す

▽上限境界 型パラメータが、あるクラスをミックスインしている事を示す



下限境界

以下のようにクラスを用意する。

class Base {}
class Super extends Base {}
class Sub   extends Super {}

class Item[+T](item: T) {}
class Foo [U](foo: Item[U]) {}
class Bar [U >: Super](bar: Item[U]) {}

最後のclass Barの[U >: Super]が下限境界。

通常class Fooのように境界がない場合、

scala> val isub = new Item(new Sub)
isub: Item[Sub] = Item@3c419631

scala> val fsub = new Foo(isub)
fsub: Foo[Sub] = Foo@3427b02d

のように、Foo[Sub]型のインスタンスが作成される。

class Barで同様の事をすると

scala> val isub = new Item(new Sub)
isub: Item[Sub] = Item@3c419631

scala> val bsub = new Bar(isub)
bsub: Bar[Super] = Bar@c8c12ac

Item[Sub]型を与えても、Item[Super]型に変換される。


具体的には、class Buf[U >: T]となっているとき、UにTのさらにサブ型の値を与える事はできない。

UがTのサブ型の場合は、暗黙的にT型に変換される。

UがTのサブ型でも、直接的なスーパー型でもない場合は、UとTの共通のスーパー型に変換される。

scala> new Bar(new Item("anyref":AnyRef))
res3: Bar[AnyRef] = Bar@291caca8

scala> new Bar(new Item("string":String))
res4: Bar[Object] = Bar@32910148



上限境界

ある型パラメータが、特定の型クラスをミックスインした型の必要があるとき、それを上限境界という形で指定できる。

class Item(val str: String) extends Ordered[Item] {
  // 抽象メソッドを実装する
  def compare(that: Item) = {
    if(this.str > that.str) 1 else 0
  }
}
class Item2 {}
class Foo [U <: Ordered[U]](foo: U) {}


scala> new Foo(new Item("string"))
res6: Foo[Item] = Foo@2e77b8cf

// Item2はOrderedをミックスインしていない
scala> new Foo(new Item2)
<console>:10: error: inferred type arguments [Item2] do not conform to class Foo's type parameter bounds [U <: Ordered[U]]
              new Foo(new Item2)
              ^
<console>:10: error: type mismatch;
 found   : Item2
 required: U
              new Foo(new Item2)
                      ^



上限境界、下限境界を同時に設定する

以下のように書く。順番は下限、上限の順。

class Bar [U >: Super <: Base](bar: U) {}