Kotlin interface default method
前言
java 在 1.8 之前,interface 是没有默认方法的。但是 kotlin 是支持在接口中定义一个默认方法的。那么 kotlin 是怎么实现的呢?本文将带你一探究竟。
Show me the code
interface TestInterface {
fun method1() {
println("default impl for method1() called")
}
fun method2()
}
class TestInterfaceCaller {
fun getTestInterfaceImpl(): TestInterface {
return object : TestInterface {
override fun method2() {
println("method2 called")
}
}
}
}
如代码所示,我们定义了一个简单的 interface 叫 TestInterface,然后在里面有两个方法:method1 和 method2 。其中,method1 是默认方法,提供了一个默认实现。然后,在使用方,也就是 TestInterfaceCaller 中,返回了一个 object : TestInterface
对象。这个对象就相当于 java 中的匿名内部类。然后,我们发现,ide 要求我们必须要实现 method2 方法,而 method1 方法不用实现。这符合我们的直观认知:因为 method1 方法是当做一个接口的默认方法来用的,method2 方法是一个接口的普通方法,所有实现这个接口的对象都要实现这个 method2 方法。
kotlin 怎么实现的?源码面前,了无秘密。
kotlin 是怎么实现 interface
默认方法的呢?要知道 java1.8 才实现的功能,kotlin 其实不要求版本就能实现。jvm 又不可能针对 kotlin 来单独开一个后门。要想知道 kotlin 是怎么实现的,我们需要对相关代码做一个反编译。结果如下:
public interface TestInterface {
void method1();
void method2();
public static final class DefaultImpls {
public static void method1(TestInterface $this) {
String var1 = "default impl for method1() called";
boolean var2 = false;
System.out.println(var1);
}
}
}
public final class TestInterfaceCaller {
@NotNull
public final TestInterface getTestInterfaceImpl() {
return (TestInterface)(new TestInterface() {
public void method2() {
String var1 = "method2 called";
boolean var2 = false;
System.out.println(var1);
}
public void method1() {
TestInterface.DefaultImpls.method1(this);
}
});
}
}
源码面前,了无秘密。我们可以看到,对于 interface
中的默认方法 method1,kotlin 其实有一个 trick:在编译期间会生成一个 DefaultImpls
的静态类,在里面有 method1
的实现。而在使用方,会在编译期间进行替换,把未实现的方法实现为对 DefaultImpls 中的静态方法的调用。