抽象型付けを使用して型処理を簡素化および明確化しようとしていますが、次のような一見無意味なエラーに遭遇し続けています。
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
C#Value
キャストを使用して 2 番目のエラーを取り除くことはできますが、それでは型を使用する意味がなくなります。
[この関連する質問] [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] { ... }
これにより、コンパイル エラーが修正され、既存のアプローチが保持されます。しかし、私はピーターの答え (以下) を正しいものとしてマークしています (彼に評判ポイントを与えます)。ありがとう、ピーター。