标签:
在Scala中有一个trait类型,它可以被继承,而且支持多重继承,其实它更像我们熟悉的接口(interface),但它与接口又有不同之处是:
trait中可以写方法的实现,interface不可以(java8开始支持接口中允许写方法实现代码了),这样看起来trait又很像抽象类(abstract),一会我们会通过反编译,看看Scala中对trait是怎样处理的,先来看看trait的使用。
//声明一个 trait
trait TraitBase{
def add(x:Int,@deprecatedName(‘y) n:Int): Int ={
return x+n
}
}
//TraitTest 继承自 TraitBase
class TraitTest extends TraitBase{
//重写父类的方法
override def add(x:Int,y:Int): Int ={
return x+y*10
}
}
//如果需要调用父类的方法,使用super访问父类
class TraitTest extends TraitBase{
override def add(x:Int,y:Int): Int ={
return super.add(x,y)*10
}
}
//使用
val test = new TraitTest
println(test.add(4,5))
对于多重继承,我们使用 with 关键字
trait A{
def FA(): Unit ={
println("FA")
}
}
trait B{
def FB(): Unit ={
println("FB")
}
}
class C{
val content=null
}
//多重继承
class D extends C with A with B{
//这里不需要必须实现trait中的方法
}
看完了使用,我们看看编译器把trait编译成什么样的java对象了。编译后有两个文件(TraitBase$class.class和TraitBase.class)
先来看看TraitBase.class
/**很熟悉吧,interface,看来trait还是跟interface有共性*/
public abstract interface TraitBase
{
public abstract int add(int paramInt1, int paramInt2);
}
再看看TraitBase$class.class
/**抽象类
它内部都是static的静态方法,但是大家注意
每个方法都带有一个参数,TraitBase 对象,通过这个对象,可以访问实际对象中定义的变量和方法
*/
public abstract class TraitBase$class
{
public static int add(TraitBase $this, int x, int n)
{
return x + n;
}
public static void $init$(TraitBase $this)
{
}
}
对于继承自trait的TraitTest,反编译结果如下
/**中规中矩的接口继承*/
public class TraitTest implements TraitBase
{
public int add(int x, int n)
{
//调用的是TraitBase$class类中的add方法,并传递了自己这个实例对象
return TraitBase.class.add(this, x, n);
}
//初始化
public TraitTest()
{
TraitBase.class.$init$(this);
}
}
属性的访问,假如有下面的Scala代码
trait TraitBase{
val content = "this is trait test"
}
class TraitTest extends TraitBase{
def Foo(): Unit ={
println(content)
}
}
反编译结果
TraitBase.class
public abstract interface TraitBase
{
/**编译器自动增加了两个接口,对content属性赋值和取值*/
//写接口,编译器自动命名,就是我们常用的stter
public abstract void scala$test$TraitBase$_setter_$content_$eq(String paramString);
//读接口,就是我们常用的getter
public abstract String content();
}
TraitBase$class.class
public abstract class TraitBase$class
{
//初始化,初始化变量
public static void $init$(TraitBase $this)
{
$this.scala$test$TraitBase$_setter_$content_$eq("this is trait test");
}
}
看来trait最终编译为interface和abstract class的两个文件
标签:
原文地址:http://blog.csdn.net/bdmh/article/details/50293693