在这个教程中,我们将深入了解 Kotlin 密封类。它们是什么?它们有什么用途?我们将在下面解决所有这些问题。
Kotlin 密封类
简而言之,顾名思义,密封类是封闭的,因此受限制。密封类用于表示受限制的类层次结构,在该结构中,对象或值只能属于其中一种类型,从而固定了类型层次结构。密封类通常在你知道给定值只能在给定选项集合中的情况下使用。
实现 Kotlin 密封类
在 Kotlin 中,密封类的实现方式如下。
sealed class A{
class B : A()
class C : A()
}
要指定密封类,需要添加修饰符 sealed
。密封类不能被实例化。因此,它们隐式地是抽象的。以下是行不通的。
fun main(args: Array<String>)
{
var a = A() //compiler error. Class A cannot be instantiated.
}
密封类的构造函数默认为私有。密封类的所有子类必须在同一个文件中声明。密封类在编译时通过限制类型集合来确保类型安全。
sealed class A{
class B : A()
{
class E : A() //this works.
}
class C : A()
init {
println("sealed class A")
}
}
class D : A() //this works
{
class F: A() //This won't work. Since sealed class is defined in another scope.
}
创建带有构造函数的密封类。
sealed class A(var name: String){
class B : A("B")
class C : A("C")
}
class D : A("D")
fun main(args: Array<String>) {
var b = A.B()
var d = D()
}
fun main(args: Array<String>) {
val e = A.E("Anupam")
println(e) //prints E(name=Anupam)
var d = A.D
d.name() //prints Object D
}
sealed class A{
class B : A()
class C : A()
object D : A()
{
fun name()
{
println("Object D")
}
}
data class E(var name: String) : A()
}
枚举和密封类的区别
在 Kotlin 中,密封类可以称为增强版的枚举类。密封类允许我们创建具有不同类型的实例,而不像枚举那样限制我们必须使用相同类型的所有枚举常量。枚举类中不可能出现以下情况。
enum class Months(string: String){
January("Jan"), February(2),
}
枚举类只允许所有常量使用单一类型。这就是密封类发挥作用的地方,它允许多个实例存在。
sealed class Months {
class January(var shortHand: String) : Months()
class February(var number: Int) : Months()
class March(var shortHand: String, var number: Int) : Months()
}
你如何在项目中使用密封类的这个特性?在类似新闻订阅的应用中,你可以创建三种不同的类类型来表示状态、图像、视频帖子,如下所示。
sealed class Post
{
class Status(var text: String) : Post()
class Image(var url: String, var caption: String) : Post()
class Video(var url: String, var timeDuration: Int, var encoding: String): Post()
}
这是枚举类无法实现的。
密封类和 when 表达式
封闭类通常与when
语句一起使用,因为每个子类及其类型都充当一个情况。此外,我们知道封闭类限制了类型。因此,when
语句的else
部分可以轻松地移除。以下示例演示了相同的。
sealed class Shape{
class Circle(var radius: Float): Shape()
class Square(var length: Int): Shape()
class Rectangle(var length: Int, var breadth: Int): Shape()
}
fun eval(e: Shape) =
when (e) {
is Shape.Circle -> println("Circle area is ${3.14*e.radius*e.radius}")
is Shape.Square -> println("Square area is ${e.length*e.length}")
is Shape.Rectangle -> println("Rectagle area is ${e.length*e.breadth}")
}
让我们按照下面所示在我们的main
函数中执行eval
函数。
fun main(args: Array) {
var circle = Shape.Circle(4.5f)
var square = Shape.Square(4)
var rectangle = Shape.Rectangle(4,5)
eval(circle)
eval(square)
eval(rectangle)
//eval(x) //compile-time error.
}
//以下内容将打印在控制台上:
//圆的面积为63.585
//正方形的面积为16
//矩形的面积为20
注意:is
修饰符检查类是否为以下类型。 is
修饰符仅对类有效。不适用于Kotlin对象,如下所示:
sealed class Shape{
class Circle(var radius: Float): Shape()
class Square(var length: Int): Shape()
object Rectangle: Shape()
{
var length: Int = 0
var breadth : Int = 0
}
}
fun eval(e: Shape) =
when (e) {
is Shape.Circle -> println("Circle area is ${3.14*e.radius*e.radius}")
is Shape.Square -> println("Square area is ${e.length*e.length}")
Shape.Rectangle -> println("Rectangle area is ${Shape.Rectangle.length*Shape.Rectangle.breadth}")
}
这就结束了kotlin封闭类教程。参考资料:Kotlin文档
Source:
https://www.digitalocean.com/community/tutorials/kotlin-sealed-class