Sealed c что это
Перейти к содержимому

Sealed c что это

  • автор:

Как использовать (в чем смысл) sealed?

То есть от класса B наследование не возможно. Ясно.

И уже тут возникает вопрос, почему не написать так

sealed class A <> //class B : A <> //Error

То есть в этом примере я конкретно показал, что наследование не возможно.
В первом примере это показано не настолько явно. Там модификатор sealed был применен к наследуемому классу B и говорилось, что уже от класса B наследование не возможно. То есть какой то третий класс не сможет наследоваться.

И далее идет ещё один пример. (Вот он третий класс Z.)

class X < protected virtual void F() < Console.WriteLine("X.F"); >protected virtual void F2() < Console.WriteLine("X.F2"); >> class Y : X < sealed protected override void F() < Console.WriteLine("Y.F"); >protected override void F2() < Console.WriteLine("Y.F2"); >> class Z : Y < // Attempting to override F causes compiler error CS0239. // protected override void F() < Console.WriteLine("Z.F"); >// Overriding F2 is allowed. protected override void F2() < Console.WriteLine("Z.F2"); >>

Обратите внимание, тут sealed идет в связке с override.

Как я понимаю — sealed — это запечатанный. То есть запечатанное не наследуется, не изменяется и т.д.
Поставили sealed — всё «броня». Никто не изменит, унаследует (за некоторыми исключениями и приемами).

Но вот этот код не верен

class classA < protected string field_1 = null; public sealed string Field_1 < get < return field_1; >set > > class classB : classA < public string Field_1 < get < return field_1; >set < if (value != "1") < field_1 = value; >> > >

Свойство Field_1 не может быть запечатанным т.к. не содержит модификатора override.
Почему? Я не хочу чтобы моё свойство было замещено или переопределено.

Вот ещё мой пример

class classA < protected string field_1 = null; public sealed virtual string Field_1 < get < return field_1; >set > //sealed нужно убрать отсюда > class classB : classA < public override string Field_1 < get < return field_1; >set < if (value != "1") < field_1 = value; >> > //sealed должно быть тут >

Аналогично. Говорит — ставь sealed к override. То есть я могу запретить переопределение свойства classB.
А в чем проблема у classA? Я хочу чтобы его свойство никто не переопределил. Ставлю sealed.
И стандартной ошибки — невозможно. т.к. запечатано не вижу.

Почему для запечатывания требуется override? Почему запечатывание свойства я могу применить только ко второму классу?

  • Вопрос задан более двух лет назад
  • 5617 просмотров

Комментировать
Решения вопроса 1

vabka

Василий Банников @vabka Куратор тега C#
Токсичный шарпист

Почему для запечатывания требуется override?

По тому что если метод не виртуальный (если у него нет модификатора virtual, override или abstract), то его и так нельзя переопределить.
По-умолчанию все методы не виртуальные

Ответ написан более двух лет назад
Комментировать
Нравится Комментировать
Ответы на вопрос 2
Victor Bomberow @majstar_Zubr
C++, C#, gamedev

Sealed переводится как «запечатанный, герметизированный». Запечатывается что именно?

1) Применение к объявлению класса. Первый пример показывает контекст применения ключевого слова. Функционал наследования запечатывается на первом же уровне наследования. В вашем контрпример не предоставляется новой информации для компилятора, поскольку на моменте компиляции компилятор сам может прийти к выводу, нужно ли при хранении объектов класса использовать указатель на таблицу виртуальных функций. Поэтому там слово sealed синтаксически верно, но лексически бесполезно.

2) Применение к объявлению члену класса. Запечатывание подразумевает наличие кое-чего, что можно запечатать. Именно — функционал наследования. Если вам нужно запечатать функционал наследования на каком-то уровне, вы это делаете. Если вы пытаетесь запечатать что-то на

уровне базового класса, то это в терминологии C# это невыражаемая мысль. Вы не должны использовать в таком случае наследование вообще (не объявлять virtual). Такую мысль могло бы выразить ключевое слово final (С++), но в C# его нет, в нём ООП используется немного в другом в контексте (где, грубо говоря, типы могут быть manged и unmanaged, и у программиста нет полного контроля над sizeof объектов типа).

Именно поэтому поведение реализовано как реализовано и

When applied to a method or property, the sealed modifier must always be used with override.

Почему запечатывание свойства я могу применить только ко второму классу?

В общем-то, функционал наследования исчисляется по уровням наследования, и там он как раз первый, а не второй. Второй класс перед глазами это первый уровень наследования и он запечатывается.

Sealed классы Java в действии: создание надежных и безопасных приложений

Sealed (закрытые или запечатанные) классы были представлены в Java 15 в качестве способа ограничить иерархию наследования класса или интерфейса.

Sealed класс или интерфейс ограничивает набор классов, которые могут наследовать или реализовывать его, что может помочь предотвратить потенциальные ошибки и сделать код более удобным в сопровождении.

Предположим, вы создаете приложение для онлайн магазина, поддерживающее несколько разных способов оплаты, а именно кредитные карты, PayPal и биткоины. Вы можете определить sealed класс PaymentMethod , который имеет список допустимых подклассов (после ключевого слова permits ) под каждый метод оплаты:

public sealed class PaymentMethod permits CreditCard, PayPal, Bitcoin < // Члены класса >

В этом примере PaymentMethod — это sealed класс, который позволяет CreditCard, PayPal и Bitcoin расширять его. Sealed класс может разрешить любому количеству классов расширить его, указав их в списке, разделенном запятыми, после ключевого слова permits .

И это только один пример того, как использование sealed класса может облегчить нашу жизнь.

Итак, давайте разбираться!

Создание иерархии закрытого типа

Sealed классы могут создавать иерархию закрытого типа. Речь идет об ограниченном наборе классов, которые не могут быть расширены или реализованы вне определенного пакета.

Это гарантирует, что могут быть использованы только классы из определенного набора, и предотвращает нежелательные расширения или реализации.

package ca.bazlur public sealed class Animal permits Cat, Dog < // Определение класса >public final class Cat extends Animal < // Определение класса >public final class Dog extends Animal < // Определение класса >

В этом примере Animal является sealed классом, который позволяет расширять его только классам Cat и Dog .

Любая другая попытка расширения Animal приведет к ошибке компиляции.

Создание ограниченного набора реализаций

Sealed классы также могут создавать ограниченный набор реализаций для определенного интерфейса или абстрактного класса. Это нужно, чтобы владельцы интерфейса или абстрактного класса могли контролировать и изменять набор реализаций.

public sealed interface Shape permits Circle, Square < double getArea(); >public final class Circle implements Shape < // Определение класса >public final class Square implements Shape < // Определение класса >

В этом примере Shape — это sealed интерфейс, который позволяет реализовать его только классам Circle и Square .

Это гарантирует, что создать любую другую реализацию Shape будет невозможно.

Улучшение паттерн матчинга в switch-конструкциях

Sealed классы также можно использовать для улучшения паттерн матчинга в операторах ветвления.

Ограничивая набор подтипов, которые могут расширять sealed класс, разработчики могут реализовать паттерн матчинг с исчерпывающими проверками, гарантируя охват всех допустимых подтипов.

public sealed abstract class PaymentMethod permits CreditCard, DebitCard, PayPal < // Определение класса >public class PaymentProcessor < public void processPayment(PaymentMethod paymentMethod, double amount) < switch (paymentMethod) < case CreditCard cc -> < // Обработка платежа кредитной картой >case DebitCard dc -> < // Обработка платежа дебетовой картой >case PayPal pp -> < // Обработка платежа по PayPal >> > >

В этом примере PaymentMethod является sealed классом, который могут расширять классы CreditCard , DebitCard и PayPal .

Метод processPayment в классе PaymentProcessor использует оператор ветвления switch с паттерн матчингом для обработки различных способов оплаты.

Использование sealed класса гарантирует, что оператором switch охватываются все возможные подтипы, благодаря чему мы защищаем себя от еще одной потенциальной ошибки.

Реализация конечного автомата

Sealed классы можно использовать для реализации конечного автомата (или стейт машины) — вычислительной модели, которая определяет поведение системы в ответ на ряд входных данных. В конечном автомате каждое состояние представлено sealed классом, а переход между состояниями реализован с помощью методов, возвращающих новое состояние.

public sealed class State permits IdleState, ActiveState, ErrorState < public State transition(Input input) < // Логика перехода >> public final class IdleState extends State < // Определение класса >public final class ActiveState extends State < // Определение класса >public final class ErrorState extends State < // Определение класса >

В этом примере State является sealed классом, который допускает подклассы IdleState , ActiveState и ErrorState .

Метод transition отвечает за переход между состояниями на основе введенного input .

Использование sealed классов гарантирует, что конечный автомат структурирован должным образом и может быть расширен только ограниченным набором классов.

Создание ограниченного набора исключений

Sealed классы также можно использовать для создания ограниченного набора исключений, которые могут быть сгенерированы методом. Это позволит вам сформировать согласованный набор условий возникновения ошибок и предотвратить создание произвольных типов исключений.

public sealed class DatabaseException extends Exception permits ConnectionException, QueryException < // Определение класса >public final class ConnectionException extends DatabaseException < // Определение класса >public final class QueryException extends DatabaseException < // Определение класса >

В этом примере DatabaseException является sealed классом, который допускает подклассы ConnectionException и QueryException .

Это гарантирует, что любое исключение, генерируемое методом, связанным с операцией над базой данных, имеет четко определенный тип и будет обработано соответствующим образом.

Управление доступом к конструкторам

Sealed классы также могут управлять доступом к конструкторам, что позволяет реализовать определенный набор инвариантов для класса.

public sealed class Person < private final String name; private final int age; private Person(String name, int age) < this.name = name; this.age = age; >public static final class Child extends Person < public Child(String name, int age) < super(name, age); if (age >= 18) < throw new IllegalArgumentException("Children must be under 18 years old."); >> > public static final class Adult extends Person < public Adult(String name, int age) < super(name, age); if (age < 18) < throw new IllegalArgumentException("Adults must be 18 years old or older."); >> > >

В этом примере Person — это sealed класс с двумя подклассами: Child и Adult .

Конструкторы для классов Child и Adult указаны как public , а конструктор для Person указан как private , в результате чего создание инстансов Person возможно только через его подклассы.

Это позволяет Person обеспечить соблюдение инварианта о том, что дети должны быть моложе 18 лет, а взрослым должно быть 18 лет или больше.

Повышение безопасности кода

Sealed классы также могут повысить безопасность кода, гарантируя, что только доверенный код может расширять или реализовывать их. Это может помочь предотвратить несанкционированный доступ к конфиденциальным частям вашей кодовой базы.

public sealed class SecureCode permits TrustedCode < // Определение класса >// Надежный код public final class TrustedCode extends SecureCode < // Определение класса >// Ненадежный код public final class UntrustedCode extends SecureCode < // Определение класса >

В этом примере SecureCode является sealed классом, который допускает только подкласс TrustedCode .

Это помогает нам гарантировать, что только доверенный код может получить доступ к конфиденциальным частям кодовой базы.

Полиморфизм с исчерпывающим паттерн матчингом

Sealed классы также можно использовать для реализации полиморфизма с исчерпывающим паттерн матчингом.

С помощью sealed классов, разработчики могут гарантировать, что все возможные подтипы охватываются оператором с паттерн матчингом, что позволяет создавать более безопасный и эффективный код.

public sealed class Shape permits Circle, Square < // Определение класса >public final class Circle extends Shape < // Определение класса >public final class Square extends Shape < // Определение класса >public void drawShape(Shape shape) < switch (shape) < case Circle c ->c.drawCircle(); case Square s -> s.drawSquare(); > >

В этом примере Shape — это sealed класс, который позволяет классам Circle и Square расширять его.

Метод drawShape использует паттерн матчинг для отрисовки фигуры, гарантируя, что все возможные подтипы Shape охватываются оператором switch .

Повышение читабельности кода

Sealed классы также можно использовать для улучшения читабельности кода за счет четкого определения набора возможных подтипов.

Ограничивая набор возможных подтипов, разработчикам легче анализировать код и понимать его поведение.

public sealed class Fruit permits Apple, Banana, Orange < // Определение класса >public final class Apple extends Fruit < // Определение класса >public final class Banana extends Fruit < // Определение класса >public final class Orange extends Fruit < // Определение класса >

В этом примере Fruit — это sealed класс, который допускает подклассы Apple , Banana и Orange .

Таким образом мы четко определяем набор допустимых фруктов и повышаем читабельность кода, облегчая его понимание.

Соблюдение контрактов API

Sealed классы также можно использовать для обеспечения соблюдения контрактов API, которые представляют собой набор ожиданий потребителей API в отношении его поведения.

Используя sealed классы, поставщики API могут гарантировать, что набор возможных подтипов четко определен и задокументирован, что повышает удобство использования и поддерживаемость API.

public sealed class Vehicle permits Car, Truck, Motorcycle < // Определение класса >public final class Car extends Vehicle < // Определение класса >public final class Truck extends Vehicle < // Определение класса >public final class Motorcycle extends Vehicle < // Определение класса >

В этом примере Vehicle — это sealed класс, который позволяет расширять его классам Car , Truck и Motorcycle .

Используя sealed класс для определения набора возможных типов транспортных средств, поставщики API могут гарантировать, что контракт API четко определен и может быть соблюден.

Предотвращение нежелательных расширений подтипов

Наконец, sealed классы также можно использовать для предотвращения нежелательных расширений подтипов.

Ограничивая набор возможных подтипов, разработчики могут предотвратить создание произвольных подклассов, которые не согласуются с предполагаемым поведением класса.

public sealed class PaymentMethod < // Определение класса >public final class CreditCard extends PaymentMethod < // Определение класса >public final class DebitCard extends PaymentMethod < // Определение класса >public class StolenCard extends PaymentMethod < // Определение класса >

В этом примере PaymentMethod является sealed классом, который не позволяет никаким подтипам расширять его.

Это предотвращает создание класса StolenCard , который не соответствует предполагаемому поведению класса PaymentMethod .

Повышение типобезопасности коллекций

Sealed классы также могут способствовать повышению типобезопасности коллекций, которые являются фундаментальной частью языка Java.

Используя sealed классы для определения набора возможных элементов в коллекции, разработчики могут гарантировать, что коллекция является типобезопасной и может энфорсить определенные инварианты.

public sealed interface Animal permits Dog, Cat, Bird < // Определение интерфейса >public final class Dog implements Animal < // Определение класса >public final class Cat implements Animal < // Определение класса >public final class Bird implements Animal < // Определение класса >

В этом примере Animal — это sealed интерфейс, который позволяет реализовать его классам Dog , Cat и Bird .

Используя sealed классы для определения набора возможных животных, разработчики могут гарантировать, что коллекция животных будет типобезопасной и может энфорсить определенные инварианты.

List animals = List.of(new Dog(), new Cat(), new Bird());

В этом примере animals — это список, содержащий элементы, которые расширяют интерфейс Animal .

Поскольку Animal — sealed интерфейс, набор возможных элементов в списке четко определен и типобезопасен.

Содействие развитию API

Sealed классы также могут способствовать развитию API, то есть обновлению API путем добавления или удаления фич.

Используя sealed классы для определения набора возможных классов, которые могут расширять или реализовывать определенный класс или интерфейс, разработчики могут обеспечить совместимость изменений API с существующим кодом.

public sealed class Animal permits Dog, Cat < // Определение класса >public final class Dog extends Animal < // Определение класса >public final class Cat extends Animal < // Определение класса >public final class Bird extends Animal < // Определение класса >

В этом примере Animal — это sealed класс, который позволяет Dog и Cat расширять его.

Поскольку Animal является sealed классом, добавление нового подтипа Bird будет критическим изменением и потребует изменения версии API.

Таким образом мы гарантируем совместимость изменений API с существующим кодом, что помогает нам поддерживать стабильность кодовой базы.

Вот еще несколько более конкретных и реальных примеров того, как sealed классы можно использовать в Java-разработке:

Представление различных типов сообщений

Во многих распределенных системах данные между различными компонентами или сервисами передаются посредством сообщений.

Sealed классы могут представлять различные типы сообщений и гарантировать, что каждый тип структурирован должным образом и типобезопасен.

public sealed interface Message permits RequestMessage, ResponseMessage < // Определение интерфейса >public final class RequestMessage implements Message < // Определение класса >public final class ResponseMessage implements Message < // Определение класса >

В этом примере Message — это sealed интерфейс, который позволяет классам RequestMessage и ResponseMessage реализовать его.

Используя sealed классы, разработчики могут гарантировать, что каждый тип сообщения является четко определенным и типобезопасным, что может помочь предотвратить ошибки и повысить удобство сопровождения кода.

Определение набора доменных объектов

В предметно‑ориентированном проектировании (DDD) доменные объекты представляют концепции и сущности предметной области.

Sealed классы могут определять набор доменных объектов и гарантировать, что каждый тип объекта четко определен и имеет ограниченный набор возможных подтипов.

public sealed interface OrderItem permits ProductItem, ServiceItem < // Определение интерфейса >public final class ProductItem implements OrderItem < // Определение класса >public final class ServiceItem implements OrderItem < // Определение класса >

В этом примере OrderItem — это sealed интерфейс, который позволяет классам ProductItem и ServiceItem реализовать его.

Используя sealed классы, разработчики могут гарантировать, что каждый доменный объект четко определен и имеет ограниченный набор возможных подтипов, что может помочь предотвратить появление ошибок и сделать код более удобным в сопровождении.

Представление различных типов пользователей

Во многих системах пользователи представляют собой лиц, так или иначе взаимодействующих с системой. Sealed классы могут представлять разные типы пользователей и гарантировать, что каждый тип структурирован должным образом и типобезопасен.

public sealed class User permits Customer, Employee, Admin < // Определение класса >public final class Customer extends User < // Определение класса >public final class Employee extends User < // Определение класса >public final class Admin extends User < // Определение класса >

В этом примере User — это sealed класс, который позволяет допускает подклассы Customer , Employee и Admin .

Используя sealed классы, разработчики могут гарантировать, что каждый пользовательский тип четко определен и типобезопасен, что может помочь предотвратить ошибки и сделать код более удобным в сопровождении.

Определение ограниченного набора типов ошибок

Во многих системах ошибки сигнализируют о том, что во время выполнения программы что‑то пошло не так.

Sealed классы могут определять ограниченный набор типов ошибок и гарантировать, что каждый тип четко определен и имеет ограниченный набор возможных подтипов.

public sealed class Error permits NetworkError, DatabaseError, SecurityError < // Определение класса >public final class NetworkError extends Error < // Определение класса >public final class DatabaseError extends Error < // Определение класса >public final class SecurityError extends Error < // Определение класса >

В этом примере Error — это sealed класс, который позволяет классам NetworkError , DatabaseError и SecurityError расширять его.

Используя запечатанные классы для определения ограниченного набора типов ошибок, разработчики могут гарантировать, что каждый тип ошибки четко определен и имеет ограниченный набор возможных подтипов, что может помочь сделать код более удобным в сопровождении и более простым для понимания.

Определение ограниченного набора HTTP-методов

Во многих веб‑приложениях взаимодействие с веб‑ресурсами происходит посредством HTTP‑методов.

Sealed классы могут определять ограниченный набор HTTP‑методов и гарантировать, что каждый метод четко определен и имеет ограниченный набор возможных подтипов.

public sealed class HttpMethod permits GetMethod, PostMethod, PutMethod < // Определение класса >public final class GetMethod extends HttpMethod < // Определение класса >public final class PostMethod extends HttpMethod < // Определение класса >public final class PutMethod extends HttpMethod < // Определение класса >

В этом примере HttpMethod — это sealed класс, который позволяет классам GetMethod , PostMethod и PutMethod расширять его.

Используя sealed классы для определения ограниченного набора HTTP‑методов, разработчики могут гарантировать, что каждый метод четко определен и имеет ограниченный набор возможных подтипов.

Это может помочь сделать код более удобным в сопровождении и более простым для понимания.

Определение ограниченного набора параметров конфигурации

Во многих системах для управления поведением программы используются специальные параметры конфигурации.

Sealed классы могут определять ограниченный набор параметров конфигурации и гарантировать, что каждый параметр четко определен и имеет ограниченный набор возможных подтипов.

public sealed class ConfigurationParameter permits DebugMode, LoggingLevel < // Определение класса >public final class DebugMode extends ConfigurationParameter < // Определение класса >public final class LoggingLevel extends ConfigurationParameter < // Определение класса >

В этом примере ConfigurationParameter является sealed классом, который позволяет классам DebugMode и LoggingLevel расширять его.

Используя sealed классы для определения ограниченного набора параметров конфигурации, разработчики могут гарантировать, что каждый параметр четко определен и имеет ограниченный набор возможных подтипов.

Это может помочь сделать код более удобным в сопровождении и более простым для понимания.

Определение ограниченного набора стратегий доступа к базе данных

Во многих системах для хранения и извлечения данных используются базы данных.

Sealed классы могут определять ограниченный набор стратегий доступа к базе данных и гарантировать, что каждая стратегия четко определена и имеет ограниченный набор возможных подтипов.

public sealed class DatabaseAccessStrategy permits JdbcStrategy, JpaStrategy, HibernateStrategy < // Определение класса >public final class JdbcStrategy extends DatabaseAccessStrategy < // Определение класса >public final class JpaStrategy extends DatabaseAccessStrategy < // Определение класса >public final class HibernateStrategy extends DatabaseAccessStrategy < // Определение класса >

В этом примере DatabaseAccessStrategy — это sealed класс, который допускает подклассы JdbcStrategy , JpaStrategy и HibernateStrategy .

Используя sealed классы для определения ограниченного набора стратегий доступа к базе данных, разработчики могут гарантировать, что каждая стратегия четко определена и имеет ограниченный набор возможных подтипов, что может помочь сделать код более удобным в сопровождении и более простым для понимания.

Определение ограниченного набора методов аутентификации

Во многих системах для проверки личности пользователей используется аутентификация.

Sealed классы могут определять ограниченный набор методов аутентификации и гарантировать, что каждый метод четко определен и имеет ограниченный набор возможных подтипов.

public sealed class AuthenticationMethod permits PasswordMethod, TokenMethod, BiometricMethod < // Определение класса >public final class PasswordMethod extends AuthenticationMethod < // Определение класса >public final class TokenMethod extends AuthenticationMethod < // Определение класса >public final class BiometricMethod extends AuthenticationMethod < // Определение класса >

В этом примере AuthenticationMethod является sealed классом, который позволяет PasswordMethod , TokenMethod и BiometricMethod расширять его.

Используя sealed классы для определения ограниченного набора методов аутентификации, разработчики могут гарантировать, что каждый метод четко определен и имеет ограниченный набор возможных подтипов.

Это может помочь сделать код более удобным в сопровождении и более простым для понимания.

Заключение

В заключение, sealed классы Java — это мощная фича, которая может помочь вам создать более надежный и удобный в сопровождении код, благодаря ограничению иерархии наследования ваших классов и интерфейсов.

Ограничив набор разрешенных подклассов или реализаторов, вы можете предотвратить ошибки и сделать свой код более безопасным и простым в обслуживании.

Освоив sealed классы Java, вы сможете вывести свои навыки программирования на новый уровень, создавая более качественное программное обеспечение.

Приглашаем всех желающих на открытое занятие «Введение в Java Collections: списки и O(n)». На занятии вы познакомитесь со списками в Java и изучите особенности их использования, получите ответ на самый популярный вопрос на собеседованиях по Java. В результате занятия будете знать основные особенности списков в java и скорости их работы. Записаться можно по ссылке.

  • Блог компании OTUS
  • Java

Запрет наследования. Ключевое слово sealed . Особенности применения. Пример

В языке C# введено ключевое слово sealed , которое используется в двух случаях:

  • когда нужно запретить наследование от некоторого класса. В многих иерархиях, классы, которые размещены на нижних уровнях могут быть обозначены как sealed ;
  • когда нужно запретить переопределение некоторого метода в иерархии классов. Эта ситуация возможна, если в иерархии классов методы унаследованных классов переопределяют виртуальные методы базовых классов.
2. Применение ключевого слова sealed для класса. Общая форма. Пример

Общая форма использования ключевого слова sealed для класса, следующая:

sealed class ClassName < // . >
  • ClassName – имя класса, который нужно запретить наследовать.

Если из класса ClassName попробовать унаследовать другой класс, то возникнет ошибка на этапе компиляции. При этом, сам класс ClassName может быть унаследован от другого класса.

Например, в следующем коде

// Класс, который запрещено наследовать sealed class A < // . > // Класс, который пробует унаследовать класс A class B : A < // . >

компилятор выдаст ошибку

'B': cannot derive from sealed type 'A'
3. Применение ключевого слова sealed для метода. Общая форма. Пример

Ключевое слово sealed может быть применено для метода также. Использование sealed для метода означает, что метод запрещено переопределять в унаследованных классах. Значит, такой метод должен быть объявлен с ключевым словом override . А это, в свою очередь, означает, что класс с sealed-методом должен наследовать другой базовый класс, который содержит метод с таким же именем.

Чтобы к методу класса применить ключевое слово sealed , нужно чтобы выполнялись следующие условия:

  • класс должен быть унаследован от другого (базового) класса;
  • в базовом классе должен быть объявлен метод, который переопределяется в данном (производном) классе. Этот метод базового класса также должен быть объявлен с ключевыми словами virtual или override (если базовый класс также унаследован).

Общая форма использования ключевого слова sealed для метода следующая:

class ClassName : BaseClassName < // . access_modifier sealed override MethodName(parameters) < // . > >
  • ClassName – имя класса, в котором объявлен sealed-метод с именем MethodName ;
  • BaseClassName – имя класса, который есть базовым для класса ClassName . Запрет переопределения метода в классе предусматривает, что этот класс унаследован от другого базового класса, в котором объявлен одноименный переопределяемый метод. Поэтому, если для некоторого метода в классе нужно применить ключевое слово sealed , этот класс обязательно должен быть унаследован от другого класса;
  • access_modifier – один из модификаторов доступа public , protected , internal , protected internal . Модификатор доступа private не может быть применен к sealed-методу;
  • MethodName – имя метода, который объявляется как sealed . Данный метод должен быть объявлен с ключевым словом override . Это значит, что данный метод переопределяет одноименный метод базового класса BaseClassName .

Пример.

Объявляется иерархия классов A , B , C . В классе C объявляется метод, который запрещено переопределять.

// Базовый класс для классов B, C class A < // Метод, который переопределяется в производных классах public virtual void Method() < Console.WriteLine("MethodA()"); > > // Класс, который наследует класс A class B : A < // В этом классе объявляется метод, который не запрещено // переопределять в производных классах public override void Method() < Console.WriteLine("MethodB()"); > > // class C : B < // Объявляется метод, который запрещено переопределять // в производных классах - с ключевым словом sealed public override sealed void Method() < Console.WriteLine("MethodC()"); > >

Если из класса C попробовать унаследовать класс D , и в классе D объявить метод, который переопределяет метод Method() класса C как показано далее

. // Класс D наследует класс C class D : C < // Ошибка! Метод Method() нельзя переопределять public override void Method() // ошибка! < Console.WriteLine("MethodD()"); > > .

то компилятор выдаст ошибку

D.Method(): cannot override inherited member C.Method() because it is sealed

Чтобы поправить ситуацию нужно выполнить одно из двух действий (в зависимости от поставленной задачи):

  • убрать слово sealed перед именем метода в классе C ;
  • поменять слово override на слово new перед именем метода в классе D .
4. Можно ли в sealed -классе объявить sealed метод?

Да, можно. В приведенном ниже примере объявляется sealed-класс и sealed-метод в этом классе.

// Базовый класс class A < // . // виртуальный метод protected virtual void Method() < >> // Класс, который наследует класс A sealed class B : A < // . // метод, который переопределяет одноименный метод базового класса protected sealed override void Method() < >>

Хотя класс B не может быть унаследован, компилятор такой код не запрещает.

Связанные темы

  • Наследование. Базовые понятия. Преимущества и недостатки. Общая форма. Простейшие примеры. Модификатор доступа protected
  • Использование конструкторов в классах при наследовании. Ключевое слово base при наследовании
  • Доступ к элементам базового класса из унаследованного класса. Ключевые слова base , new . Примеры
  • Примеры создания иерархий классов с использованием наследования

Изолированные классы в C#

Изолированные классы используются для ограничения пользователей от наследования класса. Класс можно изолировать с помощью ключевого слова sealed . Ключевое слово сообщает компилятору, что класс изолирован и, следовательно, не может быть расширен. Никакой класс не может быть производным от изолированного класса.

Ниже приводится синтаксис изолированного класса:

sealed class class_name < // data members // methods . . . >

Метод также можно изолировать, и в этом случае метод не может быть переопределен. Однако метод может быть изолирован в классах, в которых он унаследован. Если вы хотите объявить метод как изолированный, он должен быть объявлен как виртуальный в его базовом классе.

Следующий пример класса определяет изолированный класс в C#:

Далее создайте изолированный класс SealedClass и используйте его из `Program`.

// C# code to define // a Sealed Class using System; // Sealed class sealed class SealedClass < // Calling Function public int Add(int a, int b) < return a + b; >> class Program < // Main Method static void Main(string[] args) < // Creating an object of Sealed Class SealedClass slc = new SealedClass(); // Performing Addition operation int total = slc.Add(6, 4); Console.WriteLine("Total = " + total.ToString()); >> 

Вывод :

Итого = 10

Теперь, если попытаться унаследовать класс от изолированного класса, будет выдана ошибка, в которой говорится, что «Класс не может быть производным от изолированного класса .

// C# code to show restrictions // of a Sealed Class using System; class Bird < >// Creating a sealed class sealed class Test : Bird < >// Inheriting the Sealed Class class Example : Test < >// Driver Class class Program < // Main Method static void Main() < >> 

Ошибка:

Ошибка CS0509 «Пример»: не может быть производным от изолированного типа «Тест»

Рассмотрим следующий пример изолированного метода в производном классе:

// Программа C # для // демонстрации изолированного класса using System; class Printer < // Функция отображения для // вывода размеров public virtual void show() < Console.WriteLine("display dimension : 6*6"); >// Display Function public virtual void print() < Console.WriteLine("printer printing. \n"); >> // класс-наследник class LaserJet : Printer < // Sealed Display Function // for Dimension printing sealed override public void show() < Console.WriteLine("display dimension : 12*12"); >// Function to override // Print() function override public void print() < Console.WriteLine("Laserjet printer printing. \n"); >> // Класс Officejet не может переопределить метод show // метод изолирован классе родителе LaserJet. class Officejet : LaserJet < // can not override show function or else // compiler error : 'Officejet.show()' : // cannot override inherited member // 'LaserJet.show()' because it is sealed. override public void print() < Console.WriteLine("Officejet printer printing. "); >> // Driver Class class Program < // Driver Code static void Main(string[] args) < Printer p = new Printer(); p.show(); p.print(); Printer ls = new LaserJet(); ls.show(); ls.print(); Printer of = new Officejet(); of.show(); of.print(); >> 

Вывод :

размер дисплея: 6 * 6 Печать на принтере . размер дисплея: 12 * 12 Печать на принтере LaserJet . размер дисплея: 12 * 12 Печать на принтере Officejet . 

Объяснение: В приведенном выше коде C # класс Printer имеет блок отображения с размером 6 * 6, а класс LaserJet реализовал метод show , переопределив его так, чтобы он имел размер 12 * 12. Если какой-либо класс унаследует класс LaserJet , тогда он будет иметь такое же измерение 12 * 12 и не сможет реализовать собственное, т.е. он не может иметь 15 * 15, 16 * 16 или любые другие размеры. Таким образом, вызов LaserJet изолирует метод show , чтобы предотвратить его дальнейшее переопределение.

Для чего нужны изолированные классы и методы?

  • Изолированный класс используется для прекращения наследования класса. Вы не можете наследовать или расширять какой-либо класс от него.
  • Изолированный метод реализован таким образом, что никакой другой класс не может его переопределить и реализовать свой собственный метод.
  • Основная цель изолированного класса — отобрать возможность наследования у пользователя, чтобы он не мог получить класс от изолированного класса. Изолированные классы лучше всего использовать, когда у вас есть класс со статическими членами.
    например, классы “Pens” и “Brushes” пространства имен System.Drawing . Класс Pens представляет перья для стандартных цветов. Этот класс имеет только статические члены. Например, «Pens.Red» представляет собой перо красного цвета. Точно так же класс «Brushes» представляет стандартные кисти. «Brushes.Red» представляет собой кисть красного цвета.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *