当值类型具有不同数量的类型参数时,如何覆盖值?

时间:2018-03-12 01:29:37

标签: scala scala-compiler scala-2.12

为什么这很愉快地编译,

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

有解决方法吗?感谢。

2 个答案:

答案 0 :(得分: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)

(我已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)

答案 1 :(得分:1)

似乎这是 Scala编译器错误 Scala编译器将检查子类的覆盖变量是否与超类的变量匹配 类型,按checkOverride方法

DerivedBar&amp; OtherDerivedBar正在检查Existential types(这是通配符_)是否与Bar.foo匹配matchesType,但对于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)

它也被编译。