为什么这能愉快地编译,
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
有解决方法吗?谢谢。
解决方法:
目前,我不能完全阐明它为什么有效,但它有效:
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)
(我已将OtherDerivedFoo
替换为DerivedFoo2
,请参阅下面的重命名通知(
重 命名
我按如下方式重命名了这些类,以强调这两种情况之间的相似之处,并使解决方法的代码更短:
假设你有
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)
的错误,Scala 编译器将通过 checkOverride 方法检查子类的覆盖变量是否与超类的变量类型匹配,
对于DerivedBar
OtherDerivedBar
,它正在检查Existential types
(即通配符_
(是否与Bar.foo
类型匹配,但对于OtherDerivedBar
,它有2个ExistentialType,因此它将在sameLength比较方法上失败,这将导致类型不匹配。
作为Andrey的解决方案,实际上编译器将OtherDerivedBar
编译为[ClassArgsType, ExistentialType]
,这将传递sameLength
比较,因此不会抛出编译错误。
但实际上即使OtherDerivedBar
也有 2 个ExistentialType
它也应该是 Foo 的合法覆盖类型,因为:
type F = OtherDerivedFoo[_, _]
class OtherDerivedBar(override val foo: F) extends Bar(foo)
它也被编译了。