Модификатор sealed
Модификатор sealed применяется к классу или интерфейсу
и делает его закрытым для наследования и реализации
за пределами той библиотеки, в которой он объявлен.
Это позволяет создавать исчерпывающие иерархии типов,
которые удобно обрабатывать в switch.
Класс, помеченный sealed, неявно является
абстрактным, поэтому создать его экземпляр напрямую нельзя.
Наследники же могут быть объявлены только в той же
библиотеке, что и сам sealed-класс.
Поскольку sealed-класс абстрактный, его нельзя
инстанцировать. Зато компилятор знает обо всех его
наследниках, что позволяет проверять полноту ветвлений
в switch и не требовать ветку default.
Синтаксис
sealed class MyClass
{
// body
}
Пример
Давайте объявим sealed-класс Shape
и двух его наследников - Circle и Square:
sealed class Shape
{
}
class Circle extends Shape
{
final double radius;
Circle(this.radius);
}
class Square extends Shape
{
final double side;
Square(this.side);
}
void main()
{
Shape shape = Circle(2);
print(shape);
}
Результат выполнения кода:
"Instance of 'Circle'"
Пример
Главное преимущество sealed-классов - исчерпывающий
switch. Компилятор знает всех наследников, поэтому
ветка default не нужна. Давайте вычислим площадь фигуры:
sealed class Shape
{
}
class Circle extends Shape
{
final double radius;
Circle(this.radius);
}
class Square extends Shape
{
final double side;
Square(this.side);
}
double area(Shape shape)
{
return switch (shape)
{
Circle(radius: var r) => 3.14 * r * r,
Square(side: var s) => s * s,
};
}
void main()
{
print(area(Circle(2)));
print(area(Square(3)));
}
Результат выполнения кода:
"12.56"
"9.0"
Пример
Попытка унаследоваться от sealed-класса
из другой библиотеки вызовет ошибку компиляции.
А попытка создать экземпляр самого sealed-класса
приведёт к ошибке, так как он абстрактный:
sealed class Shape
{
}
void main()
{
// Shape shape = Shape(); // compile error
print('sealed class cannot be instantiated');
}
Результат выполнения кода:
"sealed class cannot be instantiated"