密封类和密封接口是 Kotlin 中允许创建受限类层次结构的两个特性。这两个构造用于定义一组有限的可能子类型,并防止在声明的层次结构之外定义其他子类型。
密封类
密封类是一个可以被子类化的类,但只能在声明它的同一个文件中进行子类化。这意味着密封类不能直接实例化,也不能在声明它的文件之外具有任何其他子类。它通常用于表示受限制的类层次结构。
以下是一个密封类的示例:
sealed class Result<out T> {
data class Success<T>(val data: T) : Result<T>()
data class Error(val error: Exception) : Result<Nothing>()
}
在这个例子中,我们有一个名为Result的密封类,它有两个子类,Success和Error。Success子类接受一个泛型类型T作为参数,该参数表示成功返回的数据。Error子类接受一个异常Exception作为参数,表示发生的错误。
-
密封类可以有带参数的构造函数,而密封接口则不行。
-
密封类可以有抽象方法和属性,而密封接口只能有抽象方法。
-
密封类可以被类、对象和其他密封类扩展,而密封接口只能被类和对象实现。
-
密封类通常与when表达式一起使用,以提供详尽的模式匹配。
示例:
sealed class Animal
class Dog(val name: String): Animal()
class Cat(val name: String): Animal()
fun makeSound(animal: Animal) = when (animal) {
is Dog -> println("${animal.name} says woof!")
is Cat -> println("${animal.name} says meow!")
}
val myDog = Dog("Rufus")
val myCat = Cat("Whiskers")
makeSound(myDog) // outputs: "Rufus says woof!"
makeSound(myCat) // outputs: "Whiskers says meow!"
密封接口
密封接口与密封类类似,但用于表示受限的接口集,而不是类。与密封类一样,密封接口将可能的子类型集合限制为在与密封接口相同的文件中定义的有限集合。
以下是一个密封接口的示例:
sealed interface State {
object Idle : State
data class Loading(val message: String) : State
data class Error(val error: Throwable) : State
data class Success(val data: Any) : State
}
在这个例子中,我们有一个名为 State 的密封接口,它有四个子类型:Idle、Loading、Error 和 Success。每个子类型代表应用可能处于的不同状态,比如应用处于空闲状态、正在加载数据、遇到错误或成功获取数据。
- 密封接口不能有带参数的构造函数,但可以有属性。
- 密封接口只能有抽象方法,但可以为这些方法提供默认实现。
- 密封接口可以被类和对象实现,但不能被其他接口或密封接口继承。
- 密封接口通常用作定义一组相关功能的方式,这些功能可以由不同的类实现。
示例:
sealed interface Animal {
val name: String
fun makeSound()
}
class Dog(override val name: String): Animal {
override fun makeSound() {
println("$name says woof!")
}
}
class Cat(override val name: String): Animal {
override fun makeSound() {
println("$name says meow!")
}
}
val myDog = Dog("Rufus")
val myCat = Cat("Whiskers")
myDog.makeSound() // outputs: "Rufus says woof!"
myCat.makeSound() // outputs: "Whiskers says meow!"
密封类用于定义一个受限制的类层次结构,而密封接口用于定义一组可以由不同类实现的相关功能。Sealed类可以有构造函数和抽象属性,而Sealed接口不能有构造函数,但可以有属性和默认方法实现。
何时使用密封类与密封接口
密封类和密封接口都可以用来定义受限制的类层次结构,但它们在不同的上下文中使用。密封类通常用于表示类的受限层次结构,而密封接口用于表示接口的受限集合。
通常,如果需要限制类层次结构的可能子类集,则应该使用密封类。如果需要限制接口的一组可能实现,则应该使用密封接口。
总之,密封类和密封接口是Kotlin中强大的功能,允许开发人员定义受限制的类层次结构,并防止在声明的层次结构之外定义其他子类型。它们在需要有限的一组可能的子类型的情况下很有用,并且可以帮助确保代码更可靠,不易出错。