Scala:trait

Scala开篇(目录)

在Scala中有一个trait类型,它可以被继承,而且支持多重继承,其实它更像我们熟悉的接口(interface),但它与接口又有不同之处是:
trait中可以写方法的实现,interface不可以(java8开始支持接口中允许写方法实现代码了),这样看起来trait又很像抽象类(abstract),一会我们会通过反编译,看看Scala中对trait是怎样处理的,先来看看trait的使用。

//声明一个 trait
trait TraitBase{
  def add(x:Int,y:Int): Int ={
    return x+y
  }
}
//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的两个文件

你可能感兴趣的:(scala)