密封类概念 II . 密封类声明 III. 密封类注意事项 IV . 密封类 示例代码 I . 密封类概念 ---- 1 . 密封类作用 : 定义一个密封类 , 该类只能有有限个指定的子类 , 不能在其它文件定义其它类型子类 ; 2 . 密封类声明 ---- 1 . 密封类声明 : 在 class 前添加 sealed 修饰符 , 即可将该类声明为密封类 ; sealed class Student{} 2 . 密封类注意事项 ---- 1 . 抽象类本质 : 密封类本质是抽象类 , 其类型不能被实例化 , 只能实例化其子类 ; 2 . 密封类子类 : ① 定义在密封类内部 ( 推荐 ) : 密封类的子类建议定义在密封类内部 , 可以兼容所有版本 ; ② 定义在密封类所在文件 : Kotlin 1.1 以后的版本 , 可以将密封类子类定义在密封类声明的同一个文件中
简介 sealed 修饰的类称为密封类,用来表示受限的类层次结构。 案例 // 外部无法实例化密封的类 // 外部只能实例化他的子类 sealed class Color { // 只能在内部继承密封类 class Red(val value: Int) Color.Red -> TODO() is Color.Green -> TODO() is Color.Blue -> TODO() } } 案例 // 默认情况下,密封类的构造函数是私有的 // 密封类的所有子类必须在同一文件中声明。 sealed class A { class B : A() { // this works. class F: A() } 案例 // 在密封的类中添加数据类和对象 sealed class A { class B : A() class C : A() object
我先翻译为密封类吧O__O "…。 什么是密封类? 官方文档:密封类用于表示受限类的层次结构,当一个值有一个有限的类型,但不能有任何其他类型。 它们在某种意义上是枚举类的扩展:枚举类型的值的集合也受到限制,但是每个枚举常量只能作为一个单独的实例存在,而一个密封类的子类可以有多个可以包含状态的实例。 如何声明密封类? data class WhitePerson(val name:String,age:Int):Person() object BlackCat:Person() } 当在表达式中使用它们时,密封类的便捷就会体现出来
而 sealed class (本文下称 "密封类" ) 则同时包含了前面两者的优势 —— 抽象类表示的灵活性和枚举里集合的受限性。 /video/BV1Nk… 密封类的基本使用 和抽象类类似,密封类可用于表示层级关系。 子类可以是任意的类: 数据类、Kotlin 对象、普通的类,甚至也可以是另一个密封类。但不同于抽象类的是,您必须把层级声明在同一文件中,或者嵌套在类的内部。 使用 when 语句处理密封类时,如果没有覆盖所有情况,可以让编译器给我们一个错误提示。 工作原理 为何密封类会拥有这些特性?
事实上,引入了几个新的关键字来支持密封类:密封和非密封。 这些类扩充了继承的经典概念,在继承概念中,只有一组特定的子类才能扩展父类。因此,本质上,Final类不允许继承。 它实际上由两个极端类组成:Final类和Abstract类,前者完全阻止继承,后者强制继承。Sealed类使开发人员能够精确地指定允许哪些子类扩展超级类。 因为有密封类,所以也有密封接口。 换句话说,密封类的子类必须声明为final、sealed或非sealed。 B {} // 喏,现在可以继承了 现在,假设我们希望类A由B和C扩展,我们也希望类D扩展类B,但我们不希望类D声明为final、非密封或密封,那么我们可以按如下方式设计类: Public sealed 密封类和子类必须位于同一个命名模块中,尽管它们可以位于不同的包中。 对于未命名的模块,密封类和子类必须在同一个包中。 Java中的密封接口 密封接口的声明方式与密封类几乎相同。
如果不对该功能的继承实现进行限制,开发人员将很容易滥用该功能的实现类,错误地重用一些代码。这就是密封类产生的原因。 密封类的声明 ❝密封类不仅仅可以是类,也可以是接口。 文章中的密封类为统称 密封类(接口)可以明确哪些类和接口可以对其扩展或实现。你可以通过sealed修饰符来表明某个类是密封类。 "); } } 密封类子类的类型 在上面示例中,密封类(接口)的实现类用了final关键字标记,当然密封类的实现类还可以是密封类: /** * 密封类子类 */ public sealed 答案是否定的,只需要使用关键字non-sealed显式声明密封类的继承实现为非密封类就可以继续扩展了。 ❝密封类中permits关键字声明的子类必须是直接子类,不可间接实现。 密封类不支持匿名类和函数式接口 由于密封类必须明确继承实现关系,所以它不支持匿名类。
如果将类看做是模板,那么抽象类就是一个不完整的模板,我们不能使用不完整的模板去构造对象。 抽象类和类成员 通过在类定义前面放置关键字 abstract,可以将类声明为抽象类。 例如,类库可以定义一个抽象类,将其用作多个类库函数的参数,并要求使用该库的程序员通过创建派生类来提供自己的类实现。 抽象类也可以定义抽象方法。 ②密封类 密封类和类成员 通过在类定义前面放置关键字 sealed,可以将类声明为密封类。 例如: public sealed class D { // Class members here. } 密封类不能用作基类。 因此,它也不能是抽象类。 密封类禁止派生。 由于密封类从不用作基类,所以有些运行时优化可以略微提高密封类成员的调用速度。 在对基类的虚成员进行重写的派生类上,方法、索引器、属性或事件可以将该成员声明为密封成员。
新特性 通过密封的类和接口来限制超类的使用,密封的类和接口限制其它可能继承或实现它们的其它类或接口。 具体使用: 使用修饰符sealed,可以将一个类声明为密封类。 密封的类使用保留关键字permits列出可以直接扩展(即extends)它的类。 final:子类为finall,间接表示父类不能被其他类继承 sealed:子类也可以声明为密封类 non-sealed:声明为非密封类,可以被其他类继承 举例: public abstract sealed //密封类 public final class Circle extends Shape {...} //子类也是一个密封类 public non-sealed class Square extends Shape {...} //non-sealed表示子类不是一个密封类,可以被任何类继承
文章目录 一、枚举类 二、枚举类定义函数 1、枚举类定义普通函数 2、枚举类定义构造函数 三、密封类 一、枚举类 ---- Kotlin 中使用 枚举类 定义常量 , 枚举类定义格式如下 : 枚举常量 main() { Gender.MALE.log() Gender.FEMALE.log() } 执行结果 : Gender, MALE 0, FEMALE 1, id = 0 三、密封类 ---- 枚举类型 是一组 子类型 闭集 ; 密封类 可以 定义 枚举类型的 子类型闭集 , 一个密封类可以有多个子类 , 继承密封类的子类 必须 与 密封类在相同的 Kotlin 代码文件中 ; 密封类适用于这种情况 , 要使用枚举的特性 , 但是需要在枚举基础上保存多个特性 ; 枚举只能实现简单的常量列举 , 如果需要更复杂的 子类型闭集 , 则需要使用密封类 ; 代码示例 : sealed class Gender { // Male 和 Female 都是 密封类 Gender 的子类 object Male: Gender() object Female: Gender() } class
Java 看 Kotlin 实现了密封类,马上给自己搞了密封类和密封接口,Kotlin 一看也立马支持了密封接口。 密封类从 Java 15 开始预览,Java 16 又预览了一波,终于在 Java 17 转正了(实际上 Java 16 和 17 的密封类是一样的)。 —— 直到 Java 也支持密封类和密封接口,Kotlin 才也对密封接口做了支持。 因此我们说密封类可以确保其直接子类可数。 密封类实际上也是一个很有用的特性,我之前在介绍 Kotlin 的密封类的时候也已经提到过不少它的用法,感兴趣的小伙伴可以看一下这个视频: 就像视频当中提到的那样,我们可以用密封类实现递归列表: public
前几天笔者提交了关于FasterKvCache的性能优化代码,其中有一个点就是我把一些后续不需要继承的类设置为了sealed密封类,然后就有小伙伴在问,为啥这个地方需要设置成sealed? // 非密封的派生类 internal class NonSealedType : BaseType { public override void Method() { } } // 密封的派生类 我们可以看到 JIT 生成后的汇编代码,可以很清楚的看到密封类少了两条指令,因为 JIT 可以从密封类中知道它不可能被继承,也不可能被重写,所以是直接跳转到密封类目标方法执行,而非密封类还有一个查表的过程 对象类型转换 (is / as) 同样有下面这样一段代码,测试密封类和非密封类的对象类型转换性能: public class SealedBenchmark { readonly BaseType IL 层面,两个方法都是一模一样: 可以看到密封类的代码相当高效,直接比较一下就转换类型返回了,而非密封类还需要 call 方法走查表流程: 数组 .NET 的数组是协变的,协变兼容的话就意味着在添加进入数组时需要检查它的类型
Int) 2.数据类声明条件 主构造函数最少要有一个参数 数据类的主构造器的所有参数必须标记为val或var 数据类不能是抽象类、open类、封闭类、内部类 数据类不能继承自任何其他类(但可以实现接口) (Koltin要修改数据类的属性,则使用其独有的copy()函数。其作用就是:修改部分属性,但是保持其他不变) 密封类 1. 但是,我们知道Kotlin的枚举类中的枚举常量是受限的,因为每一个枚举常量只能存在一个实例 但是其和枚举类不同的地方在于,密封类的一个子类可以有可包含状态的多个实例。 也可以说成,密封类是包含了一组受限的类集合,因为里面的类都是继承自这个密封类的。但是其和其他继承类(open)的区别在,密封类可以不被此文件外被继承,有效保护代码。 但是,其密封类的子类的扩展是是可以在程序中任何位置的,即可以不在同一文件下 2.声明 sealed class SealedExpr() 内部类(嵌套类) 在实际开发中,用到内部类的地方是很多的。
Sealed Classes有两种主流翻译:密封类、封闭类。个人喜欢前者多一些,所以在本文中都称为密封类。 而密封类的作用就是限制类的继承。 新手段:密封类 为了进一步增强限制能力,Java 17中的密封类增加了几个重要关键词: sealed:修饰类/接口,用来描述这个类/接口为密封类/接口 non-sealed:修饰类/接口,用来描述这个类 就可以通过引入密封类的特性来做限制。 :继续延续密封类特性,可以继续指定继承的类,并传递密封定义给子类 non-sealed:声明这个类为非密封类,可以被任意继承 final:不允许继承 根据上面的假设需求,第一、第二层稳定,允许第三层具体英雄角色可以后期不断增加新英雄
2020-9-15发布了JDK15 JDK15一共有14个新特性,其中最为笔者印象深刻的莫过于对于——密封类可以被继承 密封类从刚开始学就从各种途径了解到不能被继承,新版本的密封类如果想要被继承需要用 permits指定被继承的类 同时,被继承的类需要用final,sealed或者non-sealed修饰 正常的一个代码思路 publicclassPerson{ } classTeacherextendsPerson } //研究生 classWorkerextendsPerson{ } //工人 classRailWayWorkerextendsWorker{ } //铁路工人 这时如果想让密封类被继承就需要用 non-sealedclassWorkerextendsPerson{ } //工人 classRailWayWorkerextendsWorker{ } //铁路工人 可以看到,继承密封类的类 , 如果是密封类还要继承的话,还需要指定 如果是非密封类的话,就可以正常使用,正常被继承。
在 Java 17 中,sealed 类(密封类)就像是 ️ 皇位继承制度 ,它明确规定:哪些类可以继承自己,不允许“外人”随意篡位! 核心概念用 sealed 修饰的类,必须通过 permits 指定谁能继承它。 因为他不在 permits 名单里,无法继承“清朝皇帝”这个类。正统皇帝也可以宣布不传位给儿子们 non-sealed不再世袭罔替 实际作用 严格管控继承:避免类被随意扩展,破坏设计。 配合模式匹配:用 switch 检查密封子类时,编译器能智能判断是否覆盖所有情况。 ,需继续声明 permitsnon-sealed表示该子类不再限制继承,任何类都可继承它,等价于不使用sealed,因为语法限制,不可省略✨ 总结密封类就是 “正大光明匾后面的皇位继承名单” ,既保证了血统纯正
密封-sealed关键字 密封类、接口和特性(traits)限制了哪些子类可以扩展/实现它们。在密封类出现之前,类层次结构设计者有两个主要选择: 设置一个类关键字为final不允许扩展。 将类设为public和非final,以允许任何人扩展。 与这些要么全有要么全无的选择相比,密封类提供了一个中间地带。 密封类也比以前用于实现中间地带的其他技巧更灵活。 创建一个不可变的类Hexagon 继承Polygon类 final class Hexagon extends Polygon { } //创建一个密封类,继承Shape 仅许可Square类 sealed 然后创建的Rectangle是密封的,只允许一种控制的方法进行扩展就是Square。 密封类用于创建类似枚举的相关类,这些类需要包含特定于实例的数据。 Groovy支持注解方式创建密封类和接口,也支持使用sealed关键字创建密封类和接口。
密封性设计在生活中以及工业中具有广泛的应用,本节对现有的密封方案进行调研分析,理解各种密封的基本原理。 现有密封的方法有主要包含动密封和静密封两种,具体的应用场景如表1所示: 密封材料:随着科学技术的发展,密封技术广泛应用于高温,高压及高腐蚀性等场合,传统的密封材料如毛毡、麻丝、石棉丝、油灰等已不能满足使用要求 No.1 易拉罐密封 易拉罐在生活中具有广泛的应用,具有较好的密封性能,基本结构包含中间圆筒以及顶盖两部分(部分饮料由底盖、端盖以及圆筒三部分组成),具体如图1所示: 易拉罐通过金属材料的变形行为实现密封 ,不涉及复杂的零部件,在确保良好经济性的同时具有较高的可靠性,在生活中具有广泛的应用,不知道你对易拉罐的密封方式是否好奇呢? No.2 二重卷边工艺 二重卷边法通过两个具有不同沟槽形状的卷封滚轮,将预先翻边的罐身与法兰状的罐盖内侧周边相互卷曲、钩合、压紧,从而达到密封目的的方法,卷边过程如图所示:
垫片密封是过程工业装置中压力容器、过程设备、动力机器和连接管道等可拆连接处最主要的静密封型式。 垫片与垫片密封 垫片是一种夹持在两个独立的连接件(主要是指法兰)之间的材料或材料的组合,其作用是在预定的使用寿命内,保持两个连接件间的密封。 垫片必须能够密封结合面,并确保密封介质不渗透和不被腐蚀,能够承受得住温度和压力的作用。 非金属类法兰就必须选择预紧力要求比较小的垫片,否则很可能会有在法兰上紧过程中,垫片还没有压紧而法兰已经压碎的情况出现(如图4)。 垫片的厚度与其型式、材料、直径、密封面的加工状况和密封介质等相关。对于大多数非金属板材垫片而言,薄的垫片抵抗应力松弛的能力也比较大。
那密封类 Sealed Class就是你不可错过的一个特性。 从继承说起 Java是一门面向对象的语言,这个是我们众所周知的,而面向对象的语言的三大重要特性就是封装,继承与多态。 这就是密封类与接口要解决的问题。 密封类与接口 密封类是这样一种概念,它在允许抽象与继承的基础之上,添加约束限制。 密封类或接口,允许你对于可实现的类或可继承的类进行约束,以防止类继承或实现被突破 还是以代码来展示更为直接。 密封类 //使用sealed关键字表明这是一个密封类 public abstract sealed class Week //使用permits关键字来约束允许的子类或实现 定义一个密封类或密封接口的原则是: • 使用sealed关键字来修饰class,表明这是一个密封类 • 使用permits关键字来对可实现的类或子类进行约束 记住,类或接口,都可以使用sealed关键字
1.8 密封类背景:在 Java 中如果想让一个类不能被继承和修改,这时我们应该使用 final 关键字对类进行修饰。 Java 15 尝试解决这个问题,引入了 sealed 类,被 sealed 修饰的类可以指定子类。这样这个类就只能被指定的类继承。 JDK15的预览特性:通过密封的类和接口来限制超类的使用,密封的类和接口限制其它可能继承或实现它们的其它类或接口。具体使用:使用修饰符sealed,可以将一个类声明为密封类。 密封的类使用保留关键字permits列出可以直接扩展(即extends)它的类。 以前,为了解决空指针异常,Google在著名的Guava项目引入了Optional类,通过检查空值的方式避免空指针异常。受到Google的启发,Optional类已经成为Java 8类库的一部分。