ときどき、あるオブジェクトの型が、複数の他の型のサブタイプであると表現する必要が生じます。 Scalaでは、これは複合型を用いて表現できます。複合型とはオブジェクトの型同士を重ねることです。
2つのトレイトCloneable
とResetable
があるとしましょう。
trait Cloneable extends java.lang.Cloneable {
override def clone(): Cloneable = {
super.clone().asInstanceOf[Cloneable]
}
}
trait Resetable {
def reset: Unit
}
今、関数cloneAndReset
を書きたいとします。それはオブジェクトを受け取り、それをクローンして、元のオブジェクトをリセットします。
def cloneAndReset(obj: ?): Cloneable = {
val cloned = obj.clone()
obj.reset
cloned
}
パラメータobj
の型は何かという疑問が生じます。もしCloneable
であれば、オブジェクトをclone
することができますが、reset
することはできません。もしResetable
であれば、reset
することができますが、clone
の操作はできません。そのような状態で型キャストを回避するためにobj
の型をCloneable
とResetable
の両方であると指定することができます。Scalaではこの複合型はCloneable with Resetable
のように書くことができます。
こちらが書き変えた関数です。
def cloneAndReset(obj: Cloneable with Resetable): Cloneable = {
//...
}
複合型は複数のオブジェクトの型からなり、一つだけの細別型(refinement)を持てます。細別型は既存オブジェクトのメンバーのシグネチャを絞り込むのに使えます。
一般的な形はA with B with C ... { refinement }
です。
細別の使い方の例はミックスインを用いたクラス合成のページにあります。