编程Android开发者

描述Kotlin中抽象类和接口之间的差异。何时使用何种方法,语言中有哪些实现的特点,以及继承的细节是什么?

用 Hintsage AI 助手通过面试

答复。

在Kotlin中,抽象类abstract class)和接口interface)用于声明抽象逻辑,但它们之间存在重要差异:

  • 抽象类可以包含状态(字段),方法实现和抽象方法。一个类只能继承一个抽象类(或普通类)。抽象类可以有构造函数。
  • 接口可以包含属性声明(没有状态存储!),方法的默认实现和抽象方法。从Kotlin 1.1开始,接口可以包含属性的实现,但这些属性不能有状态。一个类可以实现多个接口。
  • 接口不能包含状态(背后字段),而抽象类则可以。

代码示例

abstract class Animal(val name: String) { abstract fun makeSound() fun info() = println("我叫 $name") } interface Movable { fun move() } class Cat(name: String) : Animal(name), Movable { override fun makeSound() = println("喵") override fun move() = println("猫在移动") }

具有欺骗性的问题。

接口在Kotlin中可以包含状态(背后字段)吗?

大多数人回答说可以在接口中声明属性,但它们仍然没有背后字段——只有没有值存储的getter/setter。即使写get() = ...——值每次都会被计算。

示例:

interface MyInterface { val value: Int get() = 42 // 没有值存储,实时计算 }

由于不知道主题的细微差别而导致的真实错误示例。


故事

在一个大型项目中,高级开发人员试图在接口中存储状态(例如,计数器),期待属性var count: Int拥有背后字段。结果是所有实现该接口的类不得不以不同方式实现值的存储,导致不稳定的逻辑(如果忘记重写setter,数据就会丢失)。


故事

一位开发人员在需要多个行为策略实现的地方(策略模式)使用了抽象类。结果出现问题:层次结构中只有一个基本类,但对于不同的行为方面却需要组合。不得不将架构更改为接口。


故事

团队尝试同时继承两个抽象类(一个带逻辑,另一个带常用工具),在Kotlin中这是不可能的。问题在扩展应用程序时显现出来。这导致了显著的技术债务,因为类必须迅速进行重新组织。