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
你不会谈论类型方面的"重写",而是缩小范围.
type T ......没有界限type T <: C... T是(C或C称为上限)的子类型type T >: C... T是C或者是超类型C(称为下限)type T = C...... T确切地说C(类型别名)因此,如果T是特征的类型成员A,并且SubA是子类型A,在情况(2)SubA可以缩小T到更特定的子类型C,而在情况(3)中它可以将其缩小到更高的超类型C.案例(1)并未对其施加任何限制SubA,而案例(4)则意味着T"最终"可以这么说.
这对于的使用性后果T的A-不管它可能显示为一个方法参数的类型或方法的返回类型.
例:
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)
它是可以定义方法m中MayNarrow1,因为类型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)