ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
## [密封类](https://www.kancloud.cn/alex_wsc/android_kotlin/1318307) 密封类用于表示受限制的类层次结构,当一个值只能在一个集合中取值,而不能取其他值时,此时可以使用密封类。在某种意义上,密封类是枚举类的扩展,即枚举类型的值集合。每个枚举常量只存在一个实例,而密封类的一个子类可以有可包含状态的多个实例。如果想要创建一个密封类必须满足以下两个条件。 (1)密封类必须用sealed关键字来修饰。 (2)由于密封类的构造函数是私有的,因此密封类的子类只能定义在密封类的内部或者同一个文件中(密封类子类的子类(间接继承者)可以放在任何位置,无需在同一个文件中!)。 示例讲解密封类 ``` 1 sealed class Stark { 2 // 罗伯•斯塔克 3 class RobStark : Stark(){} 4 // 珊莎•斯塔克 5 class SansaStark : Stark(){} 6 // 艾丽娅•斯塔克 7 class AryaStark : Stark(){} 8 // 布兰登•斯塔克 9 class BrandonStark(){} 10 } 11 // 琼恩•雪诺 12 class JonSnow : Stark(){} ``` 上述代码中,定义了一个密封类Stark,并在该类的内部定义了3个子类,分别是RobStark类、SansaStark类以及AryaStark类。BrandonStark类是该密封类的嵌套类,由于密封类的子类可以不在该密封类中,但是必须与密封类在同一个文件中,因此可知JonSnow类也是该密封类的子类。 >[info]需要注意的是,密封类的非直接继承子类(密封类子类的子类)可以声明在其他文件中。 ### 和普通继承类的区别 * 我们知道普通的继承类使用`open`关键字定义,在项目中的类都可集成至该类。 * 而密封类的子类必须是在密封类的内部或必须存在于密封类的同一文件。这一点就是上面提到的有效的代码保护。 ### Kotlin中密封类与枚举类的区别 密封类适用于子类可数的情况,而枚举类适用于实例可数的情况。 示例 ``` sealed class SealedExpr{ data class Person(val name : String, val age : Int) : SealedExpr() object Add : SealedExpr() // 单例模式 object Minus : SealedExpr() // 单例模式 } // 其子类可以定在密封类外部,但是必须在同一文件中 v1.1之前只能定义在密封类内部 object NotANumber : SealedExpr() fun main(args:Array<String>){ val mPerson1 = SealedExpr.Person("张三",22) println(mPerson1) val mPerson2 = SealedExpr.Person("李四",23) println(mPerson2) println(mPerson1.hashCode()) println(mPerson2.hashCode()) } ``` 运行结果 ``` Person(name=张三, age=22) Person(name=李四, age=23) 24021581 26103914 ``` ### 密封类的子类扩展 下面的扩展功能没有任何的意义,只是为了给大家展示密封类子类的扩展不局限与密封类同文件这一个功能而已 示例 ``` // 其存在于SealedClassDemo.kt文件中 sealed class SealedExpr{ data class Person(val name : String, val age : Int) : SealedExpr() object Add : SealedExpr() companion object Minus : SealedExpr() } object NotANumber : SealedExpr() //其存在TestSealedDemo.kt文件中 fun <T>SealedExpr.Add.add(num1 : T, num2 : T) : Int{ return 100 } fun main(args: Array<String>) { println(SealedExpr.Add.add(1,2)) } ``` 运行结果 ``` 100 ```