3

为什么这愉快地编译,

class Foo[T]

class DerivedFoo[T] extends Foo[T]

class Bar(val foo: Foo[_])

class DerivedBar(override val foo: DerivedFoo[_]) extends Bar(foo)

虽然这没有?

class OtherDerivedFoo[T, U] extends Foo[T]

class OtherDerivedBar(override val foo: OtherDerivedFoo[_, _]) extends Bar(foo)
//error: value foo overrides nothing

有解决方法吗?谢谢。

4

2 回答 2

2

解决方法:

目前,我不能很清楚地说明它为什么有效,但它有效:

import scala.language.existentials
class DerivedFoo2[T, U] extends Foo[T]
class DerivedBar2(
  override val foo: (Foo[X] with DerivedFoo2[X, _]) forSome { type X }
) extends Bar(foo)

(我已替换OtherDerivedFooDerivedFoo2,请参阅下面的重命名通知)

重命名

我已将类重命名如下,以强调两种情况之间的相似之处,并使变通方法的代码更短:

假设你有

class Foo[T]
class Bar(val foo: Foo[_])

这编译:

class DerivedFoo1[T] extends Foo[T]
class DerivedBar1(override val foo: DerivedFoo1[_])    extends Bar(foo)

但这不会:

class DerivedFoo2[T, U] extends Foo[T]
class DerivedBar2(override val foo: DerivedFoo2[_, _]) extends Bar(foo)
于 2018-03-12T02:01:45.620 回答
1

看来这是Scala编译器的错误Scala编译器会检查子类的覆盖变量是否与超类的变量 类型匹配,通过checkOverride方法,

对于DerivedBar&OtherDerivedBar它正在检查Existential types(即通配符_)是否与matchTypeBar.foo类型匹配,但因为它有2 ExistentialType,所以它会在sameLength比较方法上失败,这将导致类型不匹配。OtherDerivedBar

作为 Andrey 的解决方案,实际上编译器将编译OtherDerivedBar[ClassArgsType, ExistentialType],这将传递sameLength比较,因此不会引发编译错误。

但实际上即使OtherDerivedBar2 ExistentialType它也应该是Foo的合法覆盖类型,因为:

type F = OtherDerivedFoo[_, _]

class OtherDerivedBar(override val foo: F) extends Bar(foo)

它也被编译。

于 2018-03-12T10:30:09.503 回答