アイテムを取得する Accessor クラスがあります。また、Item をパラメーターとして取り、その Item の最新バージョンをデータベースから返すこともできます。Item を作成するとき、自分自身をパラメーターとして Item に渡します。
アクセサー インスタンスがそれ自体で作成されたアイテムのみを受け入れることを静的に要求するようコンパイラーに求めます。これは、Scala の singleton-object 型の使用方法でカバーされていましたか? ただし、Item インスタンスがそれ自体をパラメーターとして独自のアクセサーに渡して、それ自体の最新バージョンを取得できるようにすることも必要です。
これの難しさは、Item クラス定義の型パラメーターがそのようになることです。
class Item[A <: Accessor](acc: A)
acc 自体のタイプを参照することはできません。アイテムの観点からは、でacc.type <: A <: Accessor
あるthis
アイテムでは、Item[A]
ではありませんItem[acc.type]
。したがって、これは機能しません:
class Item[A <: Accessor](acc: A) {
acc.accept(this) // Type Mismatch: found Item[A], required Item[Item.this.acc.type]
}
class Accessor {
def make() = new Item[this.type](this)
def accept(item: Item[this.type]) = "accepted"
}
次に、これを試しました:
object A1 extends Accessor[A1.type](A1) // illegal cyclic reference involving object A1
class Item[+A <: Accessor[A]](acc: A) {
acc.accept(this)
A1.accept(this) // Compile error (good)
}
class Accessor[+A <: Accessor[A]](me: => A) {
def make = new Item[A](me)
def accept(item: Item[A]) = "accepted"
}
問題は実際に Accessor のインスタンスを作成することです。
上記のバリエーションを試してみましたが、同じ基本的なジレンマのより厄介な化身であることが判明しました。
object A1 extends Accessor {
type A = A1.type
def me = A1
}
class Item[+AA <: Accessor](acc: AA {type A = AA}) {
acc.accept(this)
A1.accept(this) // Compile error (good)
}
class Accessor {
type A <: Accessor
def me: A // can't do {type A = A} because its a cyclic error again
def make = new Item[A](me) // Type Mismatch: found this.A, required this.A {type A = Accessor.this.A}
def accept(item: Item[A]) = "accepted"
}
最後にA
、Item[A] が Item[acc.type] のサブタイプであり、acc によって受け入れられるように、型パラメーターを反変にしてみました。
val a1 = new Accessor
val a2 = new Accessor
val item1 = a1.make
val item2 = a2.make
val itemA = new Item[Accessor](a2)
val item12 = new Item[A1.type](a2) // compile error (good)
a1.accept(itemA) // no compile error (bad), but I can prevent creation of Item[Accessor]s
a1.accept(item2) // compile error (good)
class Item[-A <: Accessor](acc: A) {
acc.accept(this)
val acc2 = new Accessor
acc2.accept(this) // compile error (good)
// here Item[Accessor] <: Item[A] <: Item[acc.type]
// and Item[Accessor] <: Item[acc2.type]
// but Item[A] is not necessarily <: Item[acc2.type]
}
class Accessor {
def make() = new Item[this.type](this)
def accept(item: Item[this.type]) = "accepted"
}
これは、私が試したものの動作に最も近いものです。唯一の問題は、これができないため、オブジェクト階層がいっぱいになることです。
class ImmutableAccessor extends Accessor
class ImmutableItem[-A <: ImmutableAccessor](acc: A) extends Item[A] // fails due to contravariance in A
型パラメーターがシングルトン型でなければならないことを指定する方法があれば。たとえば、次のように言うことができます (I'm inventing notation here)
class Item[A:type <: Accessor](acc: A)
そしてA
、シングルトン型にacc
なり、私たちは笑っています.