关闭

Scala:trait

标签: scala
1523人阅读 评论(0) 收藏 举报
分类:

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的两个文件

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:570431次
    • 积分:5900
    • 等级:
    • 排名:第4514名
    • 原创:92篇
    • 转载:7篇
    • 译文:0篇
    • 评论:268条
    文章分类