trait 可以理解为一个实现了函数体的接口,或者胖接口
每当一个trait被创建时
会生成以接口和一个辅助抽象类。所有的函数实现部分都作为静态函数写在辅助抽象类中。主函数中中所有的调用都会直接调用抽象类中的静态函数实现。
代码
trait solver{
var value=1;
def answer():Int
def show() = {println(answer())}
def showa(a :Int) = {println(println(a))}
}
class fang extends solver{
override def answer()=42
}
public void main(String[] args)
{
fang a = new fang(); 第一步
a.show(); 第二步
a.showa(100); 第五步
}
编译后的内容 solver.class
public abstract interface solver 生成一个接口
{
public abstract int value();
public abstract void value_$eq(int paramInt);
public abstract int answer();
public abstract void show();
public abstract void showa(int paramInt);
}
编译后的内容 solver$class.class 生成一个辅助抽象类
import scala.Predef.;
import scala.runtime.BoxedUnit;
import scala.runtime.BoxesRunTime;
public abstract class solver$class
{
public static void show(solver $this)
{Predef..MODULE$.println(BoxesRunTime.boxToInteger($this.answer())); } 第四步 输出42
public static void showa(solver $this, int a) { Predef..MODULE$.println(BoxesRunTime.boxToInteger(a)); Predef..MODULE$.println(BoxedUnit.UNIT); 第七部 输出100
}
public static void $init$(solver $this)
{ $this.value_$eq(1);}
}
继承trait的类 fang.class
import scala.reflect.ScalaSignature;
import scala.runtime.TraitSetter;
public class fang implements solver
{
private int value;
public int value()
{ return this.value; }
public void value_$eq(int x$1) { this.value = x$1; }
public void show() { solver.class.show(this); } 第三步 调用最终的show函数
public void showa(int a) { solver.class.showa(this, a); } 第六步 调用最终的showa函数
public int answer() { return 42; }
public fang()
{ solver.class.$init$(this);}
}
with trait
当用了with trait时,在实现的时候会在当前类的基础上,增加ExclamatoryGreeter$class.class中所有的函数,且函数名相同,但函数体不同。
那这些函数体怎么写呢。这些函数的函数体就是调用ExclamatoryGreeter$class.class中对应的真实函数。
所以当你调用greet这个函数时,其实你调用的是当前Dog类中新增的greet函数,然后这个greet函数内才真正调用ExclamatoryGreeter$class.class中的greet函数。
ExclamatoryGreeter定义:
trait ExclamatoryGreeter{
def greet() = “Hi”
}
main函数中:
var pet = new Dog with ExclamatoryGreeter
println(pet.greet)
反编译之后Dog类
var pet = new Dog() { public String greet() { return ExclamatoryGreeter.class.greet(this); } }; 增加了ExclamatoryGreeter中定义同名的函数,并条用同名原函数
混入多个with trait1 with trait2时
假如trait1 中有个put函数,trait2中也有个put函数。scala会默认重右边开始调用,它会先调用trait2中的put函数,然后在trait2中调用trait1中的put函数
主函数.class 反编译文件
BasicIntQueue queue = new BasicIntQueue() {
public void Incrementing$$super$put(int x) { Filtering.class.put(this, x); } 第四步
public void put(int x) { Incrementing.class.put(this, x); } 第二步
public void Filtering$$super$put(int x) { super.put(x); } 第六步
};
Filtering$.class 反编译文件
public static void put(Filtering $this, int x)
{
if (x >= 0) $this.Filtering$$super$put(x); 第五步
}
Incrementing$.class 反编译文件
public static void put(Incrementing $this, int x)
{
$this.Incrementing$$super$put(x + 1); 第三步
}
主文件
new BasicIntQueue with Filtering with Incrementing 第一步
queue.put(-1)