我试图用抽象类型,以简化和澄清类型处理,但我不断遇到看似无意义的错误,像这样的:摘要和参数化类型在斯卡拉
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
是C
,不是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#值对应:
class UpdateEvent[V, C <: ValueHolder { type Value = V }](
next: V) extends Delta[C] { ... }
这可以修复这两个编译错误并保留现有方法。但我认为彼得的答案(下文)是正确的(给予他的声望点),因为我非常欣赏他的花费时间。谢谢彼得,对你最好。
真!但是,如何指定与特定价值风格相关的特定价值?我已经尝试了很多变体(C.Value,C.Value.type,在各个地方传递参数)...无济于事。 – Tim
@Tim,请检查我的更新。 –
彼得!非常感谢*刺痛了这个! (1)在update()上删除返回签名是正确的 - 好点! (2)不幸的是,这只是为了这个问题而作出的改变的副作用;在现实生活中,我无法更改(这里是什么)“update()”签名,因为我试图扩展Map和其他着名的Scala签名。可悲的是,我可能不得不更新这个问题来解释更多的限制。不过谢谢你。 – Tim