class Foo {}
class Bar[T <: Foo] {
var items : List[T] = Nil
def add(i: T) = items ::= i
}
class Fog extends Foo {
def add(bar: Bar[this.type]) = bar.add(this)
}
object Test {
val bag = new Bar[Fog]
val fog = new Fog
fog.add(bag)
}
编译器咆哮着:
Error:(20, 13) type mismatch;
found : Bar[rules.Fog]
required: Bar[rules.Test.fog.type]
Note: Fog >: Test.fog.type, but class Bar is invariant in type T.
You may wish to define T as -T instead. (SLS 4.5)
fog.add(bag)
^
但是,将T转换为-T会产生:
Error:(9, 9) contravariant type T occurs in covariant position in type => List[T] of method items
var items : List[T] = Nil
^
我想要实现的是以类型安全的方式添加到Bar [Fog]。
答案 0 :(得分:0)
您的代码暗示您想要继承Fog
,是吗?
如果没有,你可以这样做:
final class Fog extends Foo {
def add(bar: Bar[Fog]) = bar.add(this)
}
如果是,那么您将不得不重新安排您的代码,因为add需要Fog
的任何实现包(例如子类或new Fog with Mixin
):
class Foo {}
class Bar[T <: Foo] {
var items : List[T] = Nil
def add(i: T) = items ::= i
}
class Fog extends Foo {
def add(bar: Bar[this.type]) = bar.add(this)
}
trait Mixin {
def crazy = true
}
object Test {
val fog = new Fog with Mixin
// you need to tell Bar what fog actually is
val bag = new Bar[fog.type]
fog.add(bag)
}
修改强>
但是,这意味着您只能将Bar
定义的确切类型添加到bag
。
根据您的需要,您还可以在T
contra-variant 中制作Bar
,然后您可以在包中添加Fog
的不同子类型:
class Foo {}
class Bar[-T <: Foo] {
var items : List[Foo] = Nil
def add[A <: T] (i: A) = items ::= i
}
class Fog extends Foo {
def add(bar: Bar[Fog]) = bar.add(this)
}
trait Mixin {
def crazy = true
}
val fog = new Fog with Mixin
// you need to tell Bar what fog actually is
val bag = new Bar[Fog]
fog.add(bag)
(new Fog).add(bag)
// when accessing items you would have to type match, though
val test1 = bag.items.map {
case f : Fog with Mixin => 1
case f : Fog => 2
case f : Foo => 3
}
// Result: List(2, 1)