Generics 双向关联中的泛型

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]()

假设我有两个类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]()
    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)
如何工作呢?我现在正在看你的修订版,你在要求一些不可能的东西。