抽象类型
特质与抽象类可以具有抽象类型成员,这意味着具体实现将会定义这些成员的实际类型。通常,使用抽象类型的特质或类常常与匿名类实例化一起使用。
# 定义特质(使用抽象类型)
trait Buffer {
type T
val element: T
}
# 定义抽象类(使用抽象类型)
abstract class SeqBuffer extends Buffer {
type U
type T <: Seq[U]
def length = element.length
}
# 指定类型参数U
abstract class IntSeqBuffer extends SeqBuffer {
type U = Int
}
# 匿名类实例化指定抽象类型
def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer =
new IntSeqBuffer {
type T = List[U]
val element = List(elem1, elem2)
}
可以将抽象类型转为类型参数,反之亦然。
abstract class Buffer[+T] {
val element: T
}
abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] {
def length = element.length
}
def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] =
new SeqBuffer[Int, List[Int]] {
val element = List(e1, e2)
}
note:需要使用变化注解隐藏方法newIntSeqBuf返回的对象的实际序列实现类型。
note:存在一些无法将抽象类型替换为类型参数的情况。
复合类型
复合类型用于表达对象的类型同时为多个其他类型的子类型,即复合类型为对象类型的交叉点。
# 定义特质
trait Cloneable extends java.lang.Cloneable {
override def clone(): Cloneable = {
super.clone().asInstanceOf[Cloneable]
}
}
trait Resetable {
def reset: Unit
}
# 使用复合类型
# 对象obj同时为Cloneable与Resetable的子类型
def cloneAndRest(obj: Cloneable with Resetable): Cloneable={
val cloned = obj.clone()
obj.reset
cloned
}
复合类型可以由多个对象类型构成,这些对象类型可以有单个细化,用于缩短已存在对象成员的签名。通用格式:A with B with C …
自类型
自类型用于表示一个特质必须混入其他特质,即使它没有被直接扩展。这使得依赖成员可以在没有导入的情况下被使用。
自类型用于缩短this类型或其他别名为this的标识符。它的语法与函数语法类似,但是意义完全不同。
trait User {
def username: String
}
# 使用自类型
trait Tweeter {
this: User =>
def tweet(tweetText: String) = println(s"$username: $tweetText")
}
# 混入特质
class VerifiedTweeter(val username_ : String) extends Tweeter with User {
def username = s"real $username_"
}
note:扩展了Tweeter的VerifiedTweeter,必须混入User。