non*_*com 3 methods scala traits type-parameter
在我的应用程序中,我想使用这样的特性:
trait HasBuffer[+A] {
var items = Buffer[A]()
def add[A](item: A) { items += item }
def remove[A](item: A) { items -= item }
def set(is: Buffer[A]) { items = is }
def clear { items clear }
}
Run Code Online (Sandbox Code Playgroud)
继承此特征的类应该能够缓冲作为类A的子类的任何类的实例.但是,在添加和删除方法上,编译器都抱怨正在添加或删除项目"类型不匹配;找到:需要item.type(带底层类型A):".我该怎么理解这个?这里我的错误是什么,该怎么办?
您正在使用与A您的类定义不同的另一个类型参数来参数化方法.这是您使用重命名参数编写的版本:
trait HasBuffer[+A] {
var items = Buffer[A]()
def add[B](item: B) = items += item
def remove[B](item: B) { items -= item }
def set(is: Buffer[A]) { items = is }
def clear { items clear }
}
Run Code Online (Sandbox Code Playgroud)
现在应该清楚,为什么编译器会拒绝这一点.
相反,您可以简单地编写如下方法:
def add(item: A) = items += item
def remove(item: A) { items -= item }
Run Code Online (Sandbox Code Playgroud)
但是,您仍然会收到编译器错误,指出协变类型A出现在反对和不变位置.
协变的意义在于,如果你期望一个HasBuffer[AnyVal]人可以通过一个HasBuffer[Int].但是,如果您希望AnyVal并且也为该add方法使用该类型,则可以为您的类型添加完全不同的类型HasBuffer[Int].因此,编译器拒绝这一点.
相反,您必须在类型参数上提供下限,如下所示:
trait HasBuffer[+A, V <: A] {
var items = Buffer[V]()
def add(item: V) = items += item
def remove(item: V) { items -= item }
def set(is: Buffer[V]) { items = is }
def clear { items clear }
}
Run Code Online (Sandbox Code Playgroud)
有了这个,您现在可以使用以下方法:
def doSomething[X <: AnyVal](b : HasBuffer[AnyVal, X], e : X) = b.add(e)
Run Code Online (Sandbox Code Playgroud)
此方法适用于HasBuffer满足所需下限的各种类型参数组合.
在心理上将其与不提供下限的想法进行比较.然后该方法将成为这样的事情:
// doesn't make much sense!
def doSomething(b : HasBuffer[AnyVal], e : AnyVal) = b.add(e)
Run Code Online (Sandbox Code Playgroud)
如果调用此方法,类型的对象HasBuffer[Int]和Double它会高兴.你可能不会后来开心,当你发现你的缓冲区应该只包含Ints时现在包含一个Double.