当值类型具有不同数量的类型参数时,如何重写值



为什么这能愉快地编译,

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 编译器

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

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

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

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

type F = OtherDerivedFoo[_, _]
class OtherDerivedBar(override val foo: F) extends Bar(foo)

它也被编译了。

相关内容

  • 没有找到相关文章

最新更新