是否可以覆盖类型字段? [英] Is it possible to override a type field?
问题描述
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.
type T
...没有界限type T <: C
...T
是C
或C
的子类型(其中被称为上限)type T >: C
...T
是C
或C
的超类型(称为下限)type T = C
...T
正是C
(类型别名)
type T
... no boundstype T <: C
...T
isC
or a subtype ofC
(which is called upper bound)type T >: C
...T
isC
or a supertype ofC
(which is called lower bound)type T = C
...T
is exactlyC
(type alias)
因此,如果 T
是特征 A
的类型成员,并且 SubA
是 A
的子类型, 在情况 (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.
这会影响 A
中 T
的可用性——无论它是作为方法参数的类型还是作为方法的返回类型出现.
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屋!