密封类
- 密封类是限制其他类或接口可以扩展它的类或接口。
- 密封类和接口表示受限制的类层次结构,可提供对继承的更多控制。
- 密封类的所有直接子类在编译时都是已知的。带有密封类的模块编译完成后,不得出现其他子类。
-
例如, 第三方客户端无法在他们的代码中扩展您的密封类。因此,密封类的每个实例都有一个来自
编译此类时已知的有限集合。
定义密封类
要密封一个类,请将密封修饰符添加到其声明中。然后,在任何 extends 和 implements 子句之后,添加 permit 子句。该子句指定了可以扩展密封类的类。
例如,以下 Shape 声明指定了三个允许的子类,Circle、Square 和 Rectangle:
public sealed class Shape
permits Circle, Square, Rectangle {
}
在与密封类相同的模块或相同的包中定义以下三个允许的子类:Circle、Square 和 Rectangle:
public final class Circle extends Shape {
public float radius;
}
public non-sealed class Square extends Shape {
public double side;
}
public sealed class Rectangle extends Shape permits FilledRectangle {
public double length, width;
}
矩形还有一个子类,FilledRectangle:
public final class FilledRectangle extends Rectangle {
public int red, green, blue;
}
对允许的子类的限制
-
它们必须在编译时被密封类访问。
例如要编译Shape.java,编译器必须能够
访问所有允许的 Shape 类:Circle.java,
Square.java 和 Rectangle.java。另外,因为 Rectangle 是
密封类,编译器也需要访问FilledRectangle.java。
-
它们必须直接扩展密封类。
-
它们必须具有以下修饰符之一才能描述如何
它继续由其超类发起的密封:
-
final:无法进一步扩展
-
密封:只能由其允许的子类扩展
-
非密封:可以被未知子类扩展;密封类
不能阻止其允许的子类这样做
-
例如,允许的 Shape 子类演示了每个
这三个修饰符:Circle 是最终的,而 Rectangle 是密封的并且
Square 是非密封的。
-
它们必须与密封类在同一个模块中(如果密封类
类在命名模块中)或在同一个包中(如果密封
类位于未命名的模块中,如 Shape.java 示例)。
例如在下面com.example.graphics.Shape的声明中,它的permitted subclasses都在不同的包中。仅当 Shape 及其所有允许的子类位于同名模块中时,此示例才会编译。
package com.example.graphics;
public sealed class Shape
permits com.example.polar.Circle,
com.example.quad.Rectangle,
com.example.quad.simple.Square { }