什么是类型投影?类型投影有什么作用?先从内部类开始说起
Scala内部类同其成员变量一样,不同的对象实例对应的内部类是不同的,见下列代码:
scala> class Outter{
val x:Int=0
class Inner
}
defined class Outter
scala> val o1=new Outter
val o2=new Outter
o1: Outter = Outter@1ebe901
o2: Outter = Outter@7c1e7
scala> import scala.reflect.runtime.universe.typeOf
import scala.reflect.runtime.universe.typeOf
//o1.Inner与o2.Inner为不同的类型
scala> typeOf[o1.Inner]==typeOf[o2.Inner]
res0: Boolean = false
代码中定义了一个类class Outter,然后在该类中定义了一个内部类class Inner,代码val o1=new Outter、val o2=new Outter定义了两个Outter对象,通过代码typeOf[o1.Inner]==typeOf[o2.Inner]可以看到o1.Inner与o2.Inner类型不相同。这种类型不相同在使用内部类时会产生一些问题,例如
/**
* 类型投影
*/
object Example10_13 extends App{
class Outter{
val x:Int=0
//定义Outter的成员方法test,方法参数为内部类Inner
def test(i:Inner)=i
class Inner
}
val o1=new Outter
val o2=new Outter
val inner2=new o2.Inner
val inner1=new o1.Inner
//编译通过
o1.test(inner1)
//编译出错
//Error:(107, 12) typemismatch;
// found : cn.scala.chapter10.Example10_13.o2.Inner
// required:cn.scala.chapter10.Example10_13.o1.Inner
// o1.test(inner2)
// ^
o1.test(inner2)
}
在Outter类中定义了接受内部类作为成员方法test的参数,代码o1.test(inner1)能够编译通过但o1.test(inner2)会编译报错,提示类型不匹配,其本质原因是o2.Inner与o1.Inner类型不同。在讲内部类的时候提到过,内部类同成员域、成员方法并没有区别除了它是一个类外。同成员域x一样,对象o1.x与对象o2.x本质上是不同的变量,它们在内存中的存储区域不同,而对o1.Inner与o2.Inner内部类也是一样的,它们本质上是不同的类。
要使方法def test(i:Inner)=i可以同时接受o1.Inner与o2.Inner类型的对象,可以将方法定义为def test(i:Outter#Inner)=I,函数参数中的Outter#Inner称为类型投影,其作用是将o1.Inner与o2.Inner两种不同的类型投影为Outter#Inner的子类,从而使得def test(i:Outter#Inner)方法可以接受o1.Inner与o2.Inner两种类型的对象,整体代码如下:
/**
* 类型投影
*/
object Example10_13 extends App{
class Outter{
val x:Int=0
deftest(i:Outter#Inner)=i
class Inner
}
val o1=new Outter
val o2=new Outter
val inner2=new o2.Inner
val inner1=new o1.Inner
//编译通过
o1.test(inner1)
//编译通过
o1.test(inner2)
}