是否可以覆盖类型字段? [英] Is it possible to override a type field?

查看:32
本文介绍了是否可以覆盖类型字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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}
                                           ^

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

In the example above, I get an error message, that I can not override the type field in class A ( even if the chosen type subC extends the class C).

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

Is overriding a type field possible at all ? And if yes, what is wrong with the example above ?

推荐答案

关于类型,您不会说覆盖",而是要缩小它们的界限.

You wouldn't speak of 'overriding' with respect to types, but rather narrowing their bounds.

  1. type T ...没有界限
  2. type T <: C ... TCC 的子类型(其中被称为上限)
  3. type T >: C ... TCC 的超类型(称为下限)
  4. type T = C ... T 正是 C(类型别名)
  1. type T ... no bounds
  2. type T <: C ... T is C or a subtype of C (which is called upper bound)
  3. type T >: C ... T is C or a supertype of C (which is called lower bound)
  4. type T = C ... T is exactly C (type alias)

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

Therefore, if T is a type member of trait A, and SubA is a subtype of A, in case (2) SubA may narrow T to a more particular subtype C, whereas in case (3) it could narrow it to a higher supertype of C. Case (1) doesn't impose any restrictions for SubA, while case (4) means that T is 'final' so to speak.

这会影响 AT 的可用性——无论它是作为方法参数的类型还是作为方法的返回类型出现.

This has consequences for the useability of T in A—whether it may appear as a method argument's type or a method's return type.

示例:

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
}

可以在 MayNarrow1 中定义方法 m 因为类型 T 出现在 逆变位置(作为方法参数的类型),因此即使 T 被缩小到 MayNarrow1 的子类型中它仍然有效(方法体可以将 t 视为如果它是类型 C).

It is possible to define method m in MayNarrow1 because type T occurs in contravariant position (as a method argument's type), therefore it is still valid even if T is narrowed down in a subtype of MayNarrow1 (the method body can treat t as if it were type C).

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

In contrast, type T = C inevitably fixes T, which would kind of correspond to making a method final. By fixing T, it can be used in a covariant position (as a method's return type):

trait Fixed extends MayNarrow1 {
  type T = C   // make that T <: C to see that it won't compile
  final def test: T = new C {}
}

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

You can now easily see that it must be forbidden to further 'override' T:

trait Impossible extends Fixed {
  override type T = SubC

  test.bar  // oops...
}

<小时>

为了完整起见,这里是一个不太常见的下界情况:


To be complete, here is the less common case of a lower bound:

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 {}
}

这篇关于是否可以覆盖类型字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆