我试图使用抽象类型来简化和澄清类型处理,但我不断遇到这些看似无意义的错误:
trait Delta[A] {
def apply(c: A)
}
abstract class ValueHolder {
type Value
type Event <: Delta[ValueHolder]
def update(next: Value): Event = new UpdateEvent(next)
// type mismatch; found : UpdateEvent[ValueHolder]
// required: ValueHolder.this.Event
}
class UpdateEvent[C <: ValueHolder](next: C#Value) extends Delta[C] {
def apply(c: C) = c.update(next)
// type mismatch; found :
// UpdateEvent.this.next.type (with underlying type C#Value)
// required: c.Value
}
不
Delta[C]
,在哪里C <: ValueHolder
,因此符合Event <: Delta[ValueHolder]
?同样,鉴于这
c
是 aC
,不是c.Value
aC#Value
吗?
我可以使用强制转换来消除第二个错误,但这违背了使用类型的意义。
我试图将[这个相关问题] [1]中建议的答案纳入...
class UpdateEvent[C <: ValueHolder, V <: C#Value](next: V) extends Delta[C] {
...遗憾的是,这并不能缓解这两个问题(尽管从 update() 调用时它需要更多的类型参数)。
帮助???
更新:不幸的是,我上面给出的例子有点过于简单化了。我正在尝试将更改传播到具有相同方法签名的类(尽管可能是不同的类型参数),因此它们充当原始的“视图”。
例如,假设您可以运行以下命令:
(ListBuffer[Int]:_).map(_.toString)
...然后ListBuffer[String]
每次原始更新时都会更新结果。(不只是一遍又一遍地运行“map”,原因我无法简要解释。)与这个小例子一样,其他人定义了正在实现的特征,这意味着我无法更改方法签名来解决问题。
(注意:我也无法摆脱,type Event
因为有一个变量(此处未说明)包含接收每个的所有侦听Event
器——并且其类型应由子类细化以允许每个侦听器的更具体类型。)
无论如何,在思考了不是很解释性的 Scala 参考手册(信息都在那里,但假设你已经知道很多)之后,我终于想出了如何进行约束UpdateEvent
以使 C 和 C#Value 对应:
class UpdateEvent[V, C <: ValueHolder { type Value = V }](
next: V) extends Delta[C] { ... }
这修复了编译错误并保留了现有方法。但我将彼得的答案(如下)标记为正确(给他声誉积分),因为我非常感谢他花时间在这上面。谢谢,彼得,祝你好运。