kotlin密封类sealed

一. 概念

Kotlin 中的密封类(Sealed Class)是一种特殊的类,用于限制类的继承结构。密封类允许你定义一组相关的类,并且只允许这些类作为其子类存在。这种限制可以在编译时检查,从而减少了程序出错的可能性。

语法如下:

sealed class MyClass {
    // ...
}

密封类通常用于代替枚举类。密封类的优点在于可以更灵活地定义子类,而枚举类的每个成员都是固定的。密封类还可以帮助你编写更加类型安全的代码

二. 应用场景

密封类的主要应用场景是在需要表示有限数量的类型的情况下。当你知道一个类的所有可能的子类时,可以使用密封类来表示这些子类。

例如,如果你有一个表示不同任务状态的密封类 TaskState,你可以编写一个 when 表达式来处理不同的状态:

/**
 * 密封类: 任务的状态
 */
sealed class SealedTaskState {
    // 空闲
    object EMPTY : SealedTaskState()

    // 执行中
    object RUNNING : SealedTaskState()

    // 暂停中
    object PAUSE : SealedTaskState()
}

// 单元测试
@Test
fun test(sealedTaskState: SealedTaskState) {
    when (sealedTaskState) {
        // SealedTaskState有3种状态
        // 下面的数据必须包含所有的SealedTaskState里的状态,不然编译器会报错
        
        is SealedTaskState.EMPTY -> {
            println("空闲")
        }
        is SealedTaskState.RUNNING -> {
            println("执行中")
        }
        is SealedTaskState.PAUSE -> {
            println("暂停")
        }
    }
}

上面的示例中,使用了密封类封装了任务的状态,when处理了SealedTaskState所有状态发生的情况。

三. 和普通类的区别

class SealedTest {

    // 密封类测试
    @Test
    fun testSealedShape(sealedShape: SealedShape) {
        when (sealedShape) {
            is SealedCircle -> println("circle area:${sealedShape.getArea()}")
            // 'when' expression must be exhaustive, add necessary 'is SealedRectangle' branch or 'else' branch instead
            // 直接编译报错,提示必须要SealedRectangle分支或者else分支
            // is SealedRectangle -> println("rectangle area : ${sealedShape.getArea()}")
        }
    }

    // 普通类测试
    @Test
    fun testNormalShape(normalShape: NormalShape) {
        when (normalShape) {
            is NormalCircle -> println("circle area:${normalShape.getArea()}")
            // 可能出现漏掉判断的情况,比如这里,我们把普通类矩形注释了,IDE也没有提示报错
            // 但是在密封类中,在编译期我们就能看到错误
            // is NormalRectangle -> println("rectangle area : ${normalShape.getArea()}")
        }
    }
}

/**
 * 普通类: 形状
 */
abstract class NormalShape {
    // 计算面积
    abstract fun getArea(): Double
}

// 普通类: 圆形
class NormalCircle(private val radius: Double) : NormalShape() {
    override fun getArea(): Double {
        return Math.PI * radius * radius
    }
}

// 普通类: 矩形
class NormalRectangle(private val width: Double, private val height: Double) : NormalShape() {
    override fun getArea(): Double {
        return width * height
    }
}



/**
 * 密封类: 形状
 */
sealed class SealedShape {
    // 计算面积
    abstract fun getArea(): Double
}

// 密封类: 圆形
class SealedCircle(private val radius: Double) : SealedShape() {
    override fun getArea(): Double {
        return Math.PI * radius * radius
    }
}

// 密封列: 矩形
class SealedRectangle(private val width: Double, private val height: Double) : SealedShape() {
    override fun getArea(): Double {
        return width * height
    }
}

首先,没有使用密封类NormalShape的情况下,如果我们添加了新的形状类型,例如梯形或正方形,那么我们必须修改 testSealedShape 函数,以处理这些新类型的形状。其次,如果我们在 when 表达式中遗漏了某种类型的形状,那么我们将无法在编译时或运行时捕获这个错误,这可能会导致程序在处理该类型的形状时出现异常。

由于 SealedShape 是一个密封类,它的子类是有限的,编译器可以确保 when 表达式处理了所有可能的情况。如果我们添加了一个新的图形类型,我们需要添加一个新的密封子类,并实现 getArea() 方法。这个过程可以在编译时检测到错误,而不是在运行时才发现错误。这就是密封类的优势之一。

四. 总结

从上面的示例说明来看,密封类的优势可以总结为以下几点:

  1. 编译时检查:由于密封类的子类是有限的,因此编译器可以检查 when 表达式是否涵盖了所有可能的情况。这可以避免在运行时才发现未处理的情况,从而提高代码的可靠性和安全性。
  2. 类层次结构的扩展能力:通过添加新的密封子类,可以轻松地扩展现有的类层次结构,而无需修改现有的代码。这可以提高代码的可维护性和可扩展性。
  3. 更清晰的代码:密封类可以使代码更加清晰和易于理解。它可以帮助程序员更好地组织代码,从而使其更容易理解和修改。

总的来说,密封类是一种非常有用的语言特性,可以提高代码的可靠性、可维护性和可扩展性。如果您需要处理有限数量的可能情况,并且希望在编译时检测到未处理的情况,那么密封类是一个很好的选择。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kotlin 语言文档 pdf 目录 概述 4 使用 Kotlin 进行服务器端开发 4 使用 Kotlin 进行 Android 开发 5 Kotlin JavaScript 概述 6 Kotlin 1.1 的新特性 7 开始 15 基本语法 15 习惯用法 20 编码规范 24 基础 26 基本型 26 包 31 控制流:if、when、for、while 33 返回和跳转 36 与对象 38 和继承 38 属性和字段 43 接口 46 可⻅性修饰符 48 扩展 50 数据 54 密封 55 泛型 56 嵌套与内部 61 枚举 62 对象表达式和对象声明 64 委托 67 委托属性 68 函数与 Lambda 表达式 73 函数 73 高阶函数和 lambda 表达式 78 内联函数 82 协程 85 其他 89 解构声明 89 集合:List、Set、Map 91 区间 92 2型的检查与转换“is”与“as” 94 This 表达式 96 相等性 97 操作符重载 98 空安全 102 异常 104 注解 106 反射 110 型安全的构建器 113 参考 119 关键字与操作符 119 Grammar 123 Notation 123 Semicolons 123 Syntax 123 Lexical structure 130 兼容性 132 Java 互操作 135 在 Kotlin 中调用 Java 代码 135 Java 中调用 Kotlin 142 JavaScript 148 动态型 148 Kotlin 中调用 JavaScript 150 JavaScript 中调用 Kotlin 153 JavaScript 模块 155 JavaScript 反射 158 JavaScript DCE 159 示例 159 工具 160 编写 Kotlin 代码文档 160 使用 Kotlin 注解处理工具 163 使用 Gradle 165 使用 Maven 170 使用 Ant 175 Kotlin 与 OSGi 178 编译器插件 179 常⻅问题 183 FAQ 183 与 Java 语言比较 186 与 Scala 比较【官方已删除】 187

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值