面试问题——Kotlin支持多继承吗

289 阅读2分钟

前言

最近在面试的时候面试官问了一个奇怪的问题,

面试官: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);
      }
   }
}

很明显,答案就是通过静态内部类去实现的。