Generics 双向关联中的泛型
假设我有两个类A和B,B是A的子类型。显然,这只是更丰富的类型层次结构的一部分,但我认为这不相关。假设A是层次结构的根。有一个集合类C,用于跟踪a的列表。但是,我想让C成为泛型,这样就可以创建一个只保留B而不接受A的实例Generics 双向关联中的泛型,generics,inheritance,scala,bidirectional,Generics,Inheritance,Scala,Bidirectional,假设我有两个类A和B,B是A的子类型。显然,这只是更丰富的类型层次结构的一部分,但我认为这不相关。假设A是层次结构的根。有一个集合类C,用于跟踪a的列表。但是,我想让C成为泛型,这样就可以创建一个只保留B而不接受A的实例 class A(val c: C[A]) { c.addEntry(this) } class B(c: C[A]) extends A(c) class C[T <: A]{ val entries = new ArrayBuffer[T]()
class A(val c: C[A]) {
c.addEntry(this)
}
class B(c: C[A]) extends A(c)
class C[T <: A]{
val entries = new ArrayBuffer[T]()
def addEntry(e: T) { entries += e }
}
object Generic {
def main(args : Array[String]) {
val c = new C[B]()
new B(c)
}
}
及
val c = new C[A]()
new B(c)
但他会拒绝
val c = new C[B]()
new A(c)
val c = new C[B]()
new A(c)
如果有帮助的话,也许可以将C中ArrayBuffer的类型放宽为A而不是T,因此在addEntry方法中也是如此
在T中不可能使C协变(比如C[+T
在T中不可能使C协变(比如C[+THacky),但似乎可以:
class A(val c: C[A]) {
c.addEntry(this.asInstanceOf[c.X])
}
class B(c: C[B]) extends A(c)
class C[+T <: A] {
type X <: T
val entries = new ArrayBuffer[X]()
def addEntry(e: X) { entries += e }
}
object Generic {
def main(args : Array[String]) {
val c = new C(){ type T = B }
new B(c)
}
}
A类(val c:c[A]){
c、 附录(这是[c.X]的实例)
}
B类(c:c[B])扩展了A(c)
C类[+T老套,但似乎有效:
class A(val c: C[A]) {
c.addEntry(this.asInstanceOf[c.X])
}
class B(c: C[B]) extends A(c)
class C[+T <: A] {
type X <: T
val entries = new ArrayBuffer[X]()
def addEntry(e: X) { entries += e }
}
object Generic {
def main(args : Array[String]) {
val c = new C(){ type T = B }
new B(c)
}
}
A类(val c:c[A]){
c、 附录(这是[c.X]的实例)
}
B类(c:c[B])扩展了A(c)
类C[+T如果要跟踪A的实例,必须将C[A]的实例传递给B的构造函数,因为每个B也是A:
def main(args : Array[String]) {
val c = new C[A]()
new B(c)
}
然而,若你们想跟踪B,那个么你们就不能把它委托给A,因为A对B一无所知
总的来说,我觉得你的问题有点不适定。如果你想跟踪A的实例,你必须将C[A]的实例传递给B的构造函数,因为每个B也是A:
def main(args : Array[String]) {
val c = new C[A]()
new B(c)
}
然而,若你们想跟踪B,那个么你们就不能把它委托给A,因为A对B一无所知
总的来说,我觉得你的问题有点不对劲。假设这是可能的。那么你就可以这样做了:
class A(val c: C[A]) {
c.addEntry(this)
}
class B(c: C[A]) extends A(c)
class C[+T <: A]{
val entries: ArrayBuffer[T] @uncheckedVariance = new ArrayBuffer[T]()
def addEntry(e: T @uncheckedVariance) { entries += e }
}
object Generic {
def main(args : Array[String]) {
// Everything's fine so far...
val c = new C[B]()
c.addEntry(new B(c))
// but, suddenly...
val ca: C[A] = c
ca.addEntry(new A(ca))
// a problem appears!
c.entries forall {
case thing: B => true // ok
case otherThing => false // not ok -- c now contains an A!
}
}
}
及
val c = new C[A]()
new B(c)
但他会拒绝
val c = new C[B]()
new A(c)
val c = new C[B]()
new A(c)
但是,如果用C[B]
初始化B
,并且假定B
扩展了A
,那么B
将用C[B]
初始化A
,从而违反了上一个要求。假设这是可能的。那么您就可以这样做:
class A(val c: C[A]) {
c.addEntry(this)
}
class B(c: C[A]) extends A(c)
class C[+T <: A]{
val entries: ArrayBuffer[T] @uncheckedVariance = new ArrayBuffer[T]()
def addEntry(e: T @uncheckedVariance) { entries += e }
}
object Generic {
def main(args : Array[String]) {
// Everything's fine so far...
val c = new C[B]()
c.addEntry(new B(c))
// but, suddenly...
val ca: C[A] = c
ca.addEntry(new A(ca))
// a problem appears!
c.entries forall {
case thing: B => true // ok
case otherThing => false // not ok -- c now contains an A!
}
}
}
及
val c = new C[A]()
new B(c)
但他会拒绝
val c = new C[B]()
new A(c)
val c = new C[B]()
new A(c)
但是,如果用C[B]
初始化B
,并且假定B
扩展A
,则B
将用C[B]初始化A
,从而违反了最后一个要求。如果C是协变的,那么它确实会出问题,原因正是你在这里描述的,但这并不是严格意义上的要求。我认为没有任何必要将C[B]作为C[a]的子类型。@Verhoevenv如果C[B]
不是C[a]
的子类型,那么你期望如何新的B(C)
如果c
类型为c[B]
,我现在正在查看您的修订版,您要求的是一些不可能的东西。如果c是协变的,确实会出现错误,原因正是您在这里描述的,但这不是严格的要求。我认为没有必要将c[B]作为c[a]的子类型@Verhoevenv如果C[B]
不是C[a]
的子类型,那么如果C
类型为C[B]
,你希望新的B(C)
如何工作呢?我现在正在看你的修订版,你在要求一些不可能的东西。