在Kotlin的早期版本中,为了限制类型层次结构,使用了sealed类,允许开发人员通过限制在同一个文件中声明子类来显式控制允许的子类型。然而,对于某些任务来说,这不足够,特别是在需要通过接口描述类似层次结构时。为了解决这个问题,Kotlin 1.5开始引入了sealed修饰符用于接口。
普通接口允许在项目的任何地方实现它们,这常常妨碍保证类型层次结构的绝对封闭性以及使用穷尽性类型检查(exhaustive when)。这可能导致运行时错误,无法静态检查所有变体。
Sealed接口允许在一个文件内限制实现类的列表,提高了类型系统的可预测性和模式匹配的安全性。
sealed interface NetworkResult class Success(val data: String): NetworkResult class Failure(val error: Throwable): NetworkResult fun handle(result: NetworkResult) = when(result) { is Success -> println("Data: ${result.data}") is Failure -> println("Error: ${result.error}") // 所有变体都已考虑,不需要'else' }
关键特性:
可以将sealed接口添加到单独的文件中或在原始文件之外实现吗?
不可以。所有直接实现sealed接口的类型必须在同一文件中声明,否则编译器会报错。
sealed接口可以在声明文件外拥有子接口吗?
不可以。子接口也必须在同一文件中。整个层次结构在文件内部封闭。
sealed接口会影响运行时性能吗?
不会直接影响,但它们允许在编译阶段使用安全的类型检查,这减少了运行时错误的可能性,简化了代码,并可能间接加快测试速度。
开发人员在一个文件中声明sealed接口NetworkAction,但实现分散在不同的类和文件中。问题在后期被发现:编译器发出违反规则的警告,尤其是在大型项目中,修复结构变得困难。
优点:
缺点:
sealed接口OrderResult和类Success/Failure在同一个文件内部声明。when的检查始终是穷尽的,没有遗漏任何分支。
优点:
缺点: