java8之前规定java接口只能有方法定义,不能有方法实现,java8之后增加了函数式接口,函数式接口可以有一个带实现的抽象方法,scala的特质跟java的接口有点类似,但是没有java代码那样的方法实现数量限制
?
1.接口不会有构造器,特质可以有构造器,并且在实现类继承特质的时候,先要调用特质的构造器。
2.接口中不能有未初始化的属性,且属性的修饰都是public static final,特质中可以有未初始化的属性变量,即抽象字段
3.类实现implements多个接口,且用逗号“,”隔开,类继承extends多个trait且用with隔开。
4.Java中接口不能继承普通类,但是scala中特质可以extends class,并且该类成为所有继承trait的类的父类
实际的我们看例子:
public interface JavaInterface {
default void test(String agg) {
System.out.println("Interface test");
}
}
public class JavaInterfaceImpl implements JavaInterface {
public void test2(String args) {
test("Java interface test: " + args);
System.out.println("Java interface impl test" + args );
}
public static void main(String args[]) {
JavaInterfaceImpl javaInterface = new JavaInterfaceImpl();
javaInterface.test("11111");
javaInterface.test2("11111");
}
}
运行结果:
Interface test
Interface test
Java interface impl test11111
?
?
trait ScalaTraitTest {
val name:String//抽象字段
println("name: "+name)//特质中构造器执行的语句
def test(arg:String) ={
println(s"Scala Trait test $arg")
}
def test2(arg:String, arg2:String) ={
println(s"Scala Trait test2 $arg, $arg2")
}
}
class ScalaTraitClass() extends {
val name = "jack"
} with ScalaTraitTest {
def test3(arg3:String) ={
test(arg3)
test2(arg3, "2222")
println(s"Scala Trait class test 3 $arg3")
}
}
object ScalaTraitClass {
def main(args: Array[String]): Unit = {
val classTest = new ScalaTraitClass
classTest.test3("33333")
}
}
运行结果:
name: jack
Scala Trait test 33333
Scala Trait test2 33333, 2222
Scala Trait class test 3 33333
?执行结果首先打印name: jack
?
通过上面的例子,我们反推一下具体的原因,还从class文件入手,通过反编译class文件查看其实际运行
java的函数式接口反编译后是一个abstract interface,其接口的本质没有改变
?
import java.io.PrintStream;
public abstract interface JavaInterface
{
public void test(String agg)
{
System.out.println("Interface test");
}
}
?但是scala的特质反编译后有两个class文件,ScalaTraiteTest.class和ScalaTraiteTest$class.class,ScalaTraiteTest$class.class是abstrac class,这里有$init$函数,就是一个构造器,ScalaTraiteTest.class是一个abstract interface
?
?
import scala.reflect.ScalaSignature;
public abstract interface ScalaTraitTest
{
public abstract String name();
public abstract void test(String paramString);
public abstract void test2(String paramString1, String paramString2);
}
??
?
import scala.Predef.;
import scala.StringContext;
import scala.collection.mutable.StringBuilder;
public abstract class ScalaTraitTest$class
{
public static void $init$(ScalaTraitTest $this)
{
Predef..MODULE$.println(new StringBuilder().append("name: ").append($this.name()).toString());
}
public static void test(ScalaTraitTest $this, String arg)
{
Predef..MODULE$.println(new StringContext(Predef..MODULE$.wrapRefArray((Object[])new String[] { "Scala Trait test ", "" })).s(Predef..MODULE$.genericWrapArray(new Object[] { arg })));
}
public static void test2(ScalaTraitTest $this, String arg, String arg2)
{
Predef..MODULE$.println(new StringContext(Predef..MODULE$.wrapRefArray((Object[])new String[] { "Scala Trait test2 ", ", ", "" })).s(Predef..MODULE$.genericWrapArray(new Object[] { arg, arg2 })));
}
}
?
?
?我们再看其实现类ScalaTraitClass,ScalaTraitClass类确实实现了ScalaTraitTest接口,但是做了很多的事情,首先他的构造里调用了monospace;">ScalaTraitTest$class的构造器,这跟java类的构造流程一样;其次,ScalaTraitClass里面实现了接口定义的方法test和test2,但是内部实现是分别调用ScalaTraitTest$class的test和test2方法
?
import scala.Predef.;
import scala.StringContext;
import scala.reflect.ScalaSignature;
public class ScalaTraitClass
implements ScalaTraitTest
{
private final String name;
public void test(String arg)
{
ScalaTraitTest.class.test(this, arg);
}
public void test2(String arg, String arg2)
{
ScalaTraitTest.class.test2(this, arg, arg2);
}
public String name()
{
return this.name;
}
public ScalaTraitClass()
{
ScalaTraitTest.class.$init$(this);
}
public void test3(String arg3)
{
test(arg3);
test2(arg3, "2222");
Predef..MODULE$.println(new StringContext(Predef..MODULE$.wrapRefArray((Object[])new String[] { "Scala Trait class test 3 ", "" })).s(Predef..MODULE$.genericWrapArray(new Object[] { arg3 })));
}
}
?
这样来看就清晰了很多,Scala的特质是把java的抽象类和接口特性揉在了一起,这样给编程带来了很大的灵活性也方便了很多。