派生クラスでtype aliasの指定を強制する
abstractなclass or trait に、型指定のない名前だけのtype aliasを書くと、派生クラスでこのtype aliasの定義を強制することができます。
abstract class Foo( ) { // 派生クラスで明示する必要があるtype alias // このクラスの派生クラスでは、Xのtype aliasを明示しなければならない。 type X // X型はこのクラス内で使用可能。 var x:X def getX:X = x def setX(value:X):Unit = this.x=value } // Fooの派生クラスを作成。 var foo = new Foo() { // 派生クラスでX型を指定 // 指定しないとコンパイルエラーになる。 type X = String var x = "aaaa" } // メソッド呼び出し。XはStringなのでStringのメソッドが呼び出せる。 println( foo.getX.size )
実行結果です。
4
型の範囲を指定する
「<:」と「>:」でtype aliasで指定可能な型の範囲を指定できます。
- 「type <名前> <: <型>」でtype aliasを「型派生の何か」に制限できます。
- 同様に、「type <名前> >: <型>」でtype aliasは「型より上位の何か」になります。
- 「type <名前> >: <型> <: <型>」として両方指定することもできます。
abstract class Hoge( ) { // 型の範囲指定付きtype declaration type Y <: Iterable[String] // 型「Y」は「Iterable[String]派生の何か」でなければならない type Z >: Iterable[String] <: Iterable[String] // 型「Z」は「Iterable[String]より上位の何か」でなければならない // 型「Y」は「Iterable[String]派生の何か」なので、 // Iterable[String]として扱える。 var y:Y def each( p:(String)=>Unit ):Unit = y.foreach( p ) // 型「Z」は「少なくともIterable[String]」なので、 // Iterable[String]派生のオブジェクトを代入したりできる。 var z:Z = List("a", "b", "c") } // Hogeの派生クラスを作成。 var hoge = new Hoge() { // 派生クラスでY,Z型を指定 type Y = Array[String] type Z = Iterable[String] // 互換性のない型を指定するととコンパイルエラーになる。 // 以下はコンパイルエラー //type Y = Int //type Y = AnyRef //type Z = String //type Z = List[String] var y = Array( "a", "b", "c" ) } // メソッド呼び出し。 hoge.each( i=>println(i) )
実行結果です。
a b c
なお、範囲指定を省略した場合、Nothing以上Any以下になります。つまり、最初のサンプルの
type X
は
type X >: Nothing <: Any
と等価です。