定义以下内容后:
abstract class A {
type T
def print(p: T) = println(p.toString)
}
trait B extends A {
type T <: String
}
正如预期的那样,我们不能创建一个对象T = Int
:
scala> val a = new A with B {type T = Int}
<console>:9: error: overriding type T in trait B with bounds >: Nothing <: String;
type T has incompatible type
val a = new A with B {type T = Int}
^
正如预期的那样,我们可以创建一个对象T = String
:
scala> val a = new A with B {type T = String}
a: A with B{type T = String} = $anon$1@692dec
scala> a.print("test")
test
在将我们的值a
转换为 type之后,我们在调用该方法A with B
时得到一个错误。print
似乎类型字段T
丢失了有关类型(?)的信息。
scala> val b = a.asInstanceOf[A with B]
b: A with B = $anon$1@1927275
scala> b.print("test")
<console>:15: error: type mismatch;
found : java.lang.String("test")
required: b.T
b.print("test")
^
问题一:为什么在T
强制转换后类型字段的信息会丢失?
好的,所以我们再次尝试使用强制类型转换将类型字段显式设置为T
类型String
:
scala> val c = a.asInstanceOf[A with B {type T = String}]
c: A with B{type T = String} = $anon$1@1927275
scala> c.print("test")
test
好的,这行得通 - 很好。
现在让我们尝试一些疯狂的事情:
scala> val d = a.asInstanceOf[A with B {type T = Int}]
d: A with T{type T = Int} = $anon$1@1927275
scala> d.print(3)
3
问题2:嗯?TraitB
将类型限制T
为 String 的子类型,但现在该print
方法适用于整数。为什么这行得通?