trait底层原理分析

来源:互联网 发布:cad软件正版价格 编辑:程序博客网 时间:2024/06/05 03:24

本文阐述了Scala语言中, trait的底层实现原理.

trait中的变量是抽象变量

************--------------------------trait(1):抽象变量---------------------------**************

trait Property{  var name:String  val value:String}class Test1 extends Property{  override var name = "Test1"  //override可加可不加;  override val value = "Test2" //override可加可不加;}

Java里的实现:

public abstract interface Property{  public abstract String name();  public abstract void name_$eq(String paramString);  public abstract String value();}public class Test1  implements Property{  private String name = "Test1";  private final String value = "Test2";  public String name()  {    return this.name; }   public void name_$eq(String x$1) { this.name = x$1; }   public String value() { return this.value; }}
结论:

1 完全和java相等的代码; Property是一个interface, name和value都在子类Test1里面定义, 且name有存取方法,value只有取方法; 

2 也可看出, trait里面也可以定义var变量;

trait中的变量是实体变量, 子类改写

************--------------------------trait(2): var的override---------------------------**************

trait Property{  var name:String = "Property"  val value:String = "OOO"}class Test1 extends Property{  override var name = "Test1"  //会报错:overriding variable name in trait Property of type String; variable name cannot override a mutable variable;  override val value = "Test2"  //val value = "Test2"  //不加override会报错;}

看来trait中非抽象的var不能在子类里重新赋值;

trait中有可执行语句调用变量, 子类会改写变量

************--------------------------trait(3): trait里面有可执行语句---------------------------**************
trait Property{  val name:String = "name";  val value:String = "value";  println("123")}class Test1 extends Property{  override val name = "Test1"  override val value = "Test2"}

转化为Java的语句:

public abstract class Property$class{  public static void $init$(Property $this)  {    Predef..MODULE$.println("123");    $this.Property$_setter_$name_$eq("Property");    $this.Property$_setter_$value_$eq("OOO");  }}public abstract interface Property{  public abstract void Property$_setter_$name_$eq(String paramString);  public abstract void Property$_setter_$value_$eq(String paramString);  public abstract String name();  public abstract String value();}public class Test1  implements Property{  private final String name;  private final String value;  public void Property$_setter_$name_$eq(String x$1)  {  }  public void Property$_setter_$value_$eq(String x$1)  {  }  public String name()  {    return this.name; }   public String value() { return this.value; }  public Test1()  {    Property.class.$init$(this);    this.name = "Test1";    this.value = "Test2";  }}

这时的改动就大了: 
  1 由于trait里面多了可执行语句(无论是println还是变量赋值),而非单纯的抽象变量声明, 所以多出了Property$class;
2 Test1()的构造函数里面会先调用Property$class的init(), 等于会先执行trait里的语句!
3 由于trait里面有对变量定义的语句,所以trait等于多了对2个变量的存取方法,且这4个方法需要子类实现;
4 由于Test1对name和value进行了override, 所以等于Test1重写了name和value的存取方法;
5 结论是: 如果在trait里面想对name和value进行读取,是读不到的,因为子类Test1用空方法重写了变量, 而且在调用init()方法后,才会为2个变量赋值;

Test1() -> trait()的执行语句 -> Test1对变量的赋值语句;

结论:
1 trait里面是否有可执行语句, 决定了: 是否会在子类Test1()构造方法里调用trait的可执行语句;
2 trait里面是否对变量赋值(即是否为抽象类型), 决定了: 变量是否有"写访问方法";
3 子类Test1里面是否有override val name = "Test1"重写语句, 决定了: 是否会重写trait里面的"写访问方法"; 
4 当trait里面是抽象类型时, 子类里的override修饰符可以不写;
5 trait里面如果有可执行语句,那么会在子类构造器的其他语句执行前执行, 这样, trait里定义的变量, 在执行trait的语句时就不会正确赋值;

trait中有可执行语句调用变量, 子类会改写变量

************--------------------------trait(4): 使用with改善上面的问题---------------------------**************

class Test1 extends {  val name = "Test1xxxx"  val value = "Test2"} with Property用jad工具可看到:jad -p /Users/umeng/workspace_scala/20160210/out/production/20160210/Test1.classpublic class Test1    implements Property{    public String name()    {        return name;    }    public String value()    {        return value;    }    public Test1()    {        String name = "Test1xxxx";        this.name = name;        String value = "Test2";        this.value = value;        super();        Property.class.$init$(this);    }    private final String name;    private final String value;}

可看到,会先设置name和value,然后才会调用父类构造方法,然后才会调用init(); 这样在调用Property的执行语句时, name和value就已经设置好了;
见<<scala编程>>P270.
0 0
原创粉丝点击