考虑以下代码
trait Foo[T] {
def one: Foo[_ >: T]
def two: T
def three(x: T)
}
def test[T](f: Foo[T]) = {
val b = f.one
b.three(b.two)
}
方法测试无法键入check。它说:
found : (some other)_$1(in value b)
required: _$1(in value b)
val x = b.three(b.two)
如果我正确地解释了这一点,编译器认为方法测试中的b有一个看起来像这样的类型(不是合法的语法,但希望更清楚):
trait Foo {
def two: X where ∃ X >: T
def three(x: X where ∃ X >: T)
}
我所希望的是它会有这样的类型:
∃ X >: T such that trait Foo {
def two: X
def three(x: X)
}
意图是,虽然不知道精确类型X,但编译器知道它的相同未知类型由" 2"并期待"三"。这似乎与正常的通用量化泛型发生的情况不同。以下编译,但暴露了我想要隐藏的类型参数X,因为它将在Foo的实例之间变化:
trait Foo[T] {
def one[X >: T]: Foo[X]
def two: T
def three(x: T)
}
def test[T, X >: T](f: Foo[T]) = {
val b = f.one[X]
b.three(b.two)
}
有没有办法在存储量化的仿制药中获得相同的行为,当它们进行通用量化时会得到它们?
答案 0 :(得分:2)
def one: Foo[_ >: T]
相当于
def one: Foo[U >: T] forSome {type U >: T}
这个代替了
def one: Foo[U forSome {type U >: T}]
但我不明白为什么这会有所作为。好像不应该对我说。 (耸肩)
答案 1 :(得分:2)
问题是编译器认为
b.two: _>:T
b.three(_>:T)
即。两个是T的超类型,三个需要T的超类型。但是T的超类型不一定与另一个超类型T兼容,如本例所示:
A >: B >: C
def get:A
def put(B)
put(get) // type mismatch
因此,如果我们拥有的所有信息都是T的超类型,那么我们就无法安全地做到这一点。 我们必须明确告诉编译器它们是T的超类型。
trait Foo[T] {
type U <: T
def one: Foo[U]
def two: T
def three(x: T)
}
然后在实现特征时设置U
:
val x = new Foo[Dog]{
type U = Mammal
...
我希望这种方法优于存在类型,因为它具有更清晰的语法以及这是Scala的核心,并且不需要导入该功能。