gpt4 book ai didi

Scala trait 及其方法的参数化

转载 作者:行者123 更新时间:2023-12-01 09:05:04 25 4
gpt4 key购买 nike

在我的应用程序中,我想使用这样的特性:

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 }
}

继承此特征的类应该能够缓冲作为类 A 的子类的任何类的实例。但是在 add 和 remove 方法上,编译器都会提示从“类型不匹配”的项目中添加或删除项目; 找到:item.type(具有基础类型 A)需要: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 }
}

现在应该清楚了,为什么编译器会拒绝这个。

相反,您可以简单地编写如下方法:

def add(item: A) = items += item
def remove(item: A) { items -= item }

但是,您仍然会收到编译器错误,指出协变类型 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 }
}

有了这个,你现在可能有如下方法:

def doSomething[X <: AnyVal](b : HasBuffer[AnyVal, X], e : X) = b.add(e)

此方法适用于满足所需下限的各种 HasBuffer 类型参数组合。

在心理上将此与不提供下限的想法进行比较。那么方法就会变成这样:

// doesn't make much sense!
def doSomething(b : HasBuffer[AnyVal], e : AnyVal) = b.add(e)

如果你用一个 HasBuffer[Int] 类型的对象和一个 Double 来调用它,它会很高兴。不过,当您发现应该只包含 Int 的缓冲区现在包含 Double 时,您可能会不高兴。

关于Scala trait 及其方法的参数化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9128294/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com