是否可以覆盖类型字段?

Joh*_*ood 17 types scala

scala> class C
defined class C

scala> class subC extends C
defined class subC

scala> class A { type T = C}
defined class A

scala> class subA extends A { override type T = subC}
<console>:10: error: overriding type T in class A, which equals C;
 type T has incompatible type
      class subA extends A { override type T = subC}
                                           ^
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我收到一条错误消息,我无法覆盖类中的类型字段A(即使所选类型subC扩展了类C).

是否可以覆盖类型字段?如果是的话,上面的例子有什么问题?

0__*_*0__ 25

你不会谈论类型方面的"重写",而是缩小范围.

  1. type T ......没有界限
  2. type T <: C... T是(CC称为上限)的子类型
  3. type T >: C... TC或者是超类型C(称为下限)
  4. type T = C...... T确切地说C(类型别名)

因此,如果T是特征的类型成员A,并且SubA是子类型A,在情况(2)SubA可以缩小T到更特定的子类型C,而在情况(3)中它可以将其缩小到更高的超类型C.案例(1)并未对其施加任何限制SubA,而案例(4)则意味着T"最终"可以这么说.


这对于的使用性后果TA-不管它可能显示为一个方法参数的类型或方法的返回类型.

例:

trait C { def foo = () }
trait SubC extends C { def bar = () }

trait MayNarrow1 {
  type T <: C  // allows contravariant positions in MayNarrow1
  def m(t: T): Unit = t.foo  // ...like this
}

object Narrowed1 extends MayNarrow1 {
   type T = SubC
}

object Narrowed2 extends MayNarrow1 {
  type T = SubC
  override def m(t: T): Unit = t.bar
}
Run Code Online (Sandbox Code Playgroud)

它是可以定义方法mMayNarrow1,因为类型T在发生逆变位置(作为方法的参数的类型),因此它仍然是有效的,即使T在一个亚型缩小MayNarrow1(方法体可以治疗t,如果它是类型C).

相反,type T = C不可避免的修复T,这对应于制作方法final.通过固定T,它可以在协变位置使用(作为方法的返回类型):

trait Fixed extends MayNarrow1 {
  type T = C   // make that T <: C to see that it won't compile
  final def test: T = new C {}
}
Run Code Online (Sandbox Code Playgroud)

您现在可以轻松地看到必须禁止进一步"覆盖" T:

trait Impossible extends Fixed {
  override type T = SubC

  test.bar  // oops...
}
Run Code Online (Sandbox Code Playgroud)

要完成,下面是不太常见的下限:

trait MayNarrow2 {
  type T >: SubC  // allows covariant positions in MayNarrow2
  def test: T = new SubC {}
}

object Narrowed3 extends MayNarrow2 {
  type T = C
  test.foo
}

object Narrowed4 extends MayNarrow2 {
  type T = C
  override def test: T = new C {}
}
Run Code Online (Sandbox Code Playgroud)