有时需要表示对象的类型是其他几个类型的子类型。
在 Scala 中,可以使用交叉类型(或 Scala 2 中的复合类型)来表示,这些类型表现得像交叉的任何部分。
假设我们有两个特征 Cloneable
和 Resetable
trait Cloneable extends java.lang.Cloneable {
override def clone(): Cloneable = { // makes clone public
super.clone().asInstanceOf[Cloneable]
}
}
trait Resetable {
def reset: Unit
}
trait Cloneable extends java.lang.Cloneable:
override def clone(): Cloneable = // makes clone public
super.clone().asInstanceOf[Cloneable]
trait Resetable:
def reset: Unit
现在假设我们要编写一个函数 cloneAndReset
,它接收一个对象,克隆它并重置原始对象
def cloneAndReset(obj: ?): Cloneable = {
val cloned = obj.clone()
obj.reset
cloned
}
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 = {
//...
}
请注意,你可以有多种类型:A with B with C with ...
。这与 (...(A with B) with C) with ... )
是一样的
这种交集类型在 Scala 中写为 Cloneable & Resetable
。
以下是更新后的函数
def cloneAndReset(obj: Cloneable & Resetable): Cloneable = {
//...
}
请注意,你可以有多种类型:A & B & C & ...
。而且 &
是结合的,因此可以在任何部分周围添加括号,而不会改变含义。