编程Android/Kotlin开发者

什么是Kotlin中的sealed接口,如何以及为什么使用它们?

用 Hintsage AI 助手通过面试

答案。

Sealed接口是Kotlin中的一种特殊接口类型,允许限制其实现的集合在同一个模块内。封闭类最早出现在Kotlin中,而sealed接口从Kotlin 1.5开始作为对状态层次结构或事件处理等类型的更大控制的演变被添加。

问题的历史

早期开发者使用封闭类来限制继承和创建安全的层次结构。但出于灵活性和支持多重继承的结构,封闭接口变得必要。

问题

没有sealed接口,无法灵活管理接口的子类集合。这使得在处理状态时进行全面的when检查变得不可能,尤其是当一切都基于接口而非抽象类或具体类时。

解决方案

使用sealed接口可以:

  • 描述有限的实现集合。
  • 确保所有实现对于编译器都是已知的。
  • 安全地使用when而不需要else分支 — 编译器会提示未覆盖的案例。

代码示例:

sealed interface Event class Click : Event class Scroll : Event fun handle(event: Event) = when(event) { is Click -> println("点击事件") is Scroll -> println("滚动事件") }

关键特点:

  • 收窄和控制有效实现的集合。
  • 允许同时从多个sealed接口继承。
  • 在模式匹配(when)中提供安全性。

设计问题。

sealed接口是否可以在它们声明的文件之外有实现?

不,sealed接口的实现必须位于同一模块中。这确保了完整性并允许编译器控制它们的数量。

sealed接口如何与类和对象互动?

封闭接口可以被普通类、object类以及data object(Kotlin 1.9+)实现。这样的接口可以出现在多重继承中,而这在sealed类中是无法做到的。

sealed interface Operation object Add: Operation object Subtract: Operation

sealed接口可以嵌套吗?

是的,可以在另一个sealed类内部或在其他接口上方声明sealed接口。关键是所有实现都应位于同一模块中。

常见错误和反模式

  • 在不同模块中定义sealed接口的实现会导致编译错误。
  • 试图根据假设使用sealed接口,认为它像sealed类,尽管sealed接口可以被其他接口继承。

真实案例

负面案例

在应用程序中,UI状态简单地通过没有sealed修饰符的接口来描述。遗漏了一种实现,静态分析未发现此问题;错误仅在生产环境中被发现。

优点:

  • 习惯于Java接口的模式。

缺点:

  • 在when中没有穷举的保证。
  • 漏洞可能导致“外部”实现的出现。

正面案例

在屏幕事件模型中使用sealed接口。所有实现都在同一模块的一个文件中,编译器在when中遗漏的分支上会发出警告。

优点:

  • 完全的类型安全。
  • 方便支持和扩展。

缺点:

  • 只能在同一模块内使用。