scala 编译成java_Scala特征如何编译为Java字节码?

为了便于讨论,让我们看一下下面的Scala示例,该示例使用多个特征同时具有抽象方法和具体方法:

trait A {

def foo(i: Int) = ???

def abstractBar(i: Int): Int

}

trait B {

def baz(i: Int) = ???

}

class C extends A with B {

override def abstractBar(i: Int) = ???

}

目前(即从Scala 2.11开始),单个特征编码为:

一个default,其中包含所有特征特性方法的抽象声明(抽象的和具体的)

一个抽象静态类,其中包含用于所有特性的所有具体方法的静态方法,并带有一个额外的参数default(在较旧的Scala中,该类不是抽象的,但对其进行实例化没有任何意义)

在特性混入的继承层次结构的每个点上,针对特性中所有具体方法的综合转发器方法,这些方法转发给静态类的静态方法

这种编码的主要优点是,没有具体成员的特征(与接口同构)实际上被编译为接口。

interface A {

int foo(int i);

int abstractBar(int i);

}

abstract class A$class {

static void $init$(A $this) {}

static int foo(A $this, int i) { return ???; }

}

interface B {

int baz(int i);

}

abstract class B$class {

static void $init$(B $this) {}

static int baz(B $this, int i) { return ???; }

}

class C implements A, B {

public C() {

A$class.$init$(this);

B$class.$init$(this);

}

@Override public int baz(int i) { return B$class.baz(this, i); }

@Override public int foo(int i) { return A$class.foo(this, i); }

@Override public int abstractBar(int i) { return ???; }

}

但是,Scala 2.12需要Java 8,因此能够在接口中使用默认方法和静态方法,结果看起来像这样:

interface A {

static void $init$(A $this) {}

static int foo$(A $this, int i) { return ???; }

default int foo(int i) { return A.foo$(this, i); };

int abstractBar(int i);

}

interface B {

static void $init$(B $this) {}

static int baz$(B $this, int i) { return ???; }

default int baz(int i) { return B.baz$(this, i); }

}

class C implements A, B {

public C() {

A.$init$(this);

B.$init$(this);

}

@Override public int abstractBar(int i) { return ???; }

}

如您所见,保留了带有静态方法和转发器的旧设计,它们只是折叠到了接口中。 特质的具体方法现在已作为default方法移入接口本身,转发器方法并非在每个类中都被综合,而是一次定义为A$class方法,并且静态B$class方法(代表特质主体中的代码)已被使用。 也移入了接口,因此不需要伴随的静态类。

可以这样简化:

interface A {

static void $init$(A $this) {}

default int foo(int i) { return ???; };

int abstractBar(int i);

}

interface B {

static void $init$(B $this) {}

default int baz(int i) { return ???; }

}

class C implements A, B {

public C() {

A.$init$(this);

B.$init$(this);

}

@Override public int abstractBar(int i) { return ???; }

}

我不确定为什么没有这样做。 乍一看,当前的编码可能会给我们带来一些前向兼容性:您可以将使用新编译器编译的特征与旧编译器编译的类一起使用,这些旧类将简单地覆盖它们从接口继承的default504转发器方法。 相同的。 除此之外,转发器方法将尝试调用不再存在的A$class和2960383251623445445506上的静态方法,以使假设的前向兼容性实际上不起作用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值