我最近一直在使用复合类型,最近我尝试使用以下代码:
import scala.reflect._
object Main {
def main(args: Array[String]) {
val a1 = classTag[Int with String with Double].newArray(3)
println(a1.mkString(" "))
val a2 = classTag[String with Int with Double].newArray(3)
println(a2.mkString(" "))
val a3 = classTag[Double with Int with String].newArray(3)
println(a3.mkString(" "))
}
}
使用以下输出:
0 0 0
null null null
0.0 0.0 0.0
这对我来说有点奇怪。每个数组元素都可以访问三种类型的方法:Int,String和Double。这里到底发生了什么?复合类型实际上是第一种类型的实例?复合类型可以显式实例化吗?他们的用例仅适用于组成复合的类型通过继承相关的情况等等?感谢。
P.S。:我使用Scala 2.11.4
答案 0 :(得分:3)
这里的幕后发生了什么?复合类型实际上是第一种类型的实例吗?
查看为newArray
定义的ClassTag
方法:
override def newArray(len: Int): Array[T] =
runtimeClass match {
case java.lang.Byte.TYPE => new Array[Byte](len).asInstanceOf[Array[T]]
case java.lang.Integer.TYPE => new Array[Int](len).asInstanceOf[Array[T]]
/* snip */
case _ => java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]]
}
然后你的类型:
scala> classTag[Int with String with Double].runtimeClass
res4: Class[_] = int
似乎很清楚它是如何得出使用第一种类型的结论的。 runtimeClass
Int with String with Double
为Int
,newArray
方法使用runtimeClass
构建新Array
。因此Array
填充了默认的Int
值。同样适用于其他订单组合。
为什么运行时类Int
?好吧,Int with String with Double
不是真正的类,但Int
是。{1}}。编译器选择使用哪个类只能是任意的,为什么不是第一个呢?
复合类型是否可以显式实例化?
我不确定你的意思。如果你考虑一下,编译器必须支持这种组合中的一种类型。明确的Int with String with Double
会是什么样的?那么Int with String with Double with Product with Process
呢?我也不知道。
每个数组元素都可以访问三种类型的方法:Int,String和Double
他们这样做,但他们没有。
scala> val arr = classTag[Int with Process].newArray(3)
arr: Array[Int with Process] = Array(0, 0, 0)
scala> arr(0).exitValue()
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Process
你真的只是欺骗编译器相信你有Array
这些类型,而实际上你不是(而且不能,因为没有什么可以是一个子 - Int
和Process
)的类型。
它们的用例仅适用于组成复合的类型通过继承等相关的情况?
差不多,是的。如果您想要尝试直接构建这些类型的任何情况,我无法思考。它们的主要用例是保证类型继承自其他特定类型。
例如,一个方法要求参数从两个特征继承方法:
trait Hello { def hello = println("Hello") }
trait Bye { def bye = println("Bye") }
def greet(hb: Hello with Bye): Unit = { hb.hello; hb.bye }
class A extends Hello
class B extends Hello with Bye
scala> greet(new A)
<console>:15: error: type mismatch;
found : A
required: Hello with Bye
greet(new A)
^
scala> greet(new B)
Hello
Bye