В чем разница между конечным и незапечатанным классом в функции закрытых классов Java 15?

#java #sealed-class #java-15 #java-sealed-type

#java #sealed-class #java-15 #java-sealed-type

Вопрос:

У меня есть следующий запечатанный интерфейс (Java 15):

 public sealed interface Animal permits Cat, Duck {

    String makeSound();
}
  

Этот интерфейс реализован 2 классами:

 public final class Cat implements Animal {

    @Override
    public String makeSound() {
        return "miau";
    }
}

public non-sealed class Duck implements Animal {

    @Override
    public String makeSound() {
        return "quack";
    }
}
  

Может кто-нибудь сказать мне разницу между final и non-sealed ? final останавливает меня от создания других подклассов, но к какому поведению non-sealed применимо Duck ?

Комментарии:

1. Разрешенный подкласс может быть объявлен незапечатанным, так что его часть иерархии становится открытой для расширения неизвестными подклассами. (Закрытый класс не может запретить своим разрешенным подклассам делать это.)

2. final Класс никогда не может быть подклассом (старая, старая функциональность). non-sealed Класс специально открывает класс для подкласса, который необходим, когда его базовый класс sealed .

3. Запечатывание — это обобщение завершенности; конечный класс не может быть расширен ничем, закрытый класс — явным списком разрешенных подтипов. (Конечный класс похож на выбранный класс с пустым списком разрешений.) Другие языки пошли по пути, согласно которому разрешенный подтип закрытого типа может быть произвольно расширен, но это часто удивляет людей и может привести к ошибкам. Итак, Java требует, чтобы вы четко указывали на это: для подтипа закрытого типа вы должны выбрать один: final, sealed или open для расширения. (Записи неявно являются окончательными, поэтому вам не нужно указывать это явно.)

Ответ №1:

  • Как вы отметили Cat как final , никакой другой класс не может расширяться Cat .
  • Как вы отметили Duck как non-sealed , любой класс может расширяться Duck .

При пометке класса как sealed все непосредственно расширяемые классы (те, что после permits предложения) должны быть помечены либо как final , sealed либо non-sealed :

  • Пометка класса, который расширяет sealed класс как sealed , применяет к нему тот же эффект: только классам, указанным после permits предложения, разрешено его расширять.

  • non-sealed просто «разрывает печать», поэтому эффект не нужно переносить вниз по иерархии. Расширяемый класс открыт (снова) для расширения самими неизвестными подклассами.

  • final фактически то же sealed самое, что и без какого-либо класса, указанного после permits предложения. Обратите внимание, что указание ничего после permits невозможно, поэтому sealed не может заменить final .

Комментарии:

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

Ответ №2:

Конечный и незапечатанный классы имеют некоторые различия.

конечный класс: вы не можете наследовать этот класс. Я имею в виду, что вы не можете расширить этот класс на другой класс, с другой стороны.

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

Например:
этот запечатанный интерфейс, интерфейс которого разрешен только для класса Cat amp; Duck.Обратите внимание, что Cat amp; Duck должен быть конечным, не запечатанным или запечатанным классом

 public sealed interface Animal permits Cat, Duck {
  String makeSound();
}
  

Теперь я создаю класс Cat amp; Duck. Здесь Cat является конечным классом, а другой — незапечатанным классом.

 public final class Cat implements Animal {

    @Override
    public String makeSound() {
        return "miau";
    }
}

public non-sealed class Duck implements Animal {

    @Override
    public String makeSound() {
        return "quack";
    }
}
  

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

 //Got Error
public class MyCat extends Cat {

 .......
}

//Error not show.Duck class is extendable
public class MyDuck extends Duck {

    .....
}
  

Ответ №3:

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

Когда вы помечаете класс как запечатанный, только разрешенные подклассы могут расширять его и могут иметь только эти модификаторы final, sealed или non-sealed:

 public sealed class NumberSystem
    // The permits clause has been omitted
    // as all the subclasses exists in the same file.
{ }
non-sealed class Decimal extends NumberSystem { .. }
final class NonRecurringDecimal extends Decimal {..}
final class RecurringDecimal extends Decimal {..}
  

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

Комбинация sealed и non-sealed позволяет ограничить части вашей иерархии, но не все.

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