前言
最近在面试的时候面试官问了一个奇怪的问题,
面试官:Java支持多继承吗
我:不支持
面试官:那Kotlin呢
我:应该也不支持吧
面试官:...你去百度一下看看呢
我:此时心里一万个尴尬。。。
面试完我立马去查了一下,原来Kotlin还真的可以实现多继承,不得不说自己的知识面还有很多没有补充到的地方啊。
言归正传
Kotlin怎么去实现的多继承呢,答案就是用接口的方式,因为类是只能继承一个的,但是接口却可以实现多个。
Java的接口的方法默认是不能有方法体的,虽然JDK8提供了方法体的支持(只需要用default关键字修饰接口方法)
而Kotlin接口的方法默认支持方法体。
写个例子吧,比如说人这个动物吧,他有时候是好人,有时候又是坏人,有时候会做好事,有时候又会去做坏事,那么用Kotlin来描述一下看看。
interface GoodMan {
fun introduce() {
println("我是好人")
}
fun doThing() {
println("扶老太太过马路")
}
}
interface BadMan {
fun introduce() {
println("我是坏人")
}
fun doThing() {
println("赌博打架欺负小朋友")
}
}
class Person : GoodMan, BadMan {
override fun introduce() {
// 好人坏人总是不是绝对的,一个人有时是好人有时是坏人
if (System.currentTimeMillis() % 2 == 0L) {
super<GoodMan>.introduce()
} else {
super<BadMan>.introduce()
}
}
override fun doThing() {
// 做好事和坏事也不是绝对的
if (System.currentTimeMillis() % 2 == 0L) {
super<GoodMan>.doThing()
} else {
super<BadMan>.doThing()
}
}
}
fun main() {
val person = Person()
person.introduce()
person.doThing()
}
那么Kotlin是怎么实现的默认支持方法体呢,反编译成Java看下吧
- BadMan
public interface BadMan {
void introduce();
void doThing();
public static final class DefaultImpls {
public static void introduce(@NotNull BadMan $this) {
String var1 = "我是坏人";
System.out.println(var1);
}
public static void doThing(@NotNull BadMan $this) {
String var1 = "赌博打架欺负小朋友";
System.out.println(var1);
}
}
}
- GoodMan
public interface GoodMan {
void introduce();
void doThing();
public static final class DefaultImpls {
public static void introduce(@NotNull GoodMan $this) {
String var1 = "我是好人";
System.out.println(var1);
}
public static void doThing(@NotNull GoodMan $this) {
String var1 = "扶老太太过马路";
System.out.println(var1);
}
}
}
- Person
public final class Person implements GoodMan, BadMan {
public void introduce() {
if (System.currentTimeMillis() % (long)2 == 0L) {
GoodMan.DefaultImpls.introduce(this);
} else {
BadMan.DefaultImpls.introduce(this);
}
}
public void doThing() {
if (System.currentTimeMillis() % (long)2 == 0L) {
GoodMan.DefaultImpls.doThing(this);
} else {
BadMan.DefaultImpls.doThing(this);
}
}
}
很明显,答案就是通过静态内部类去实现的。