Ответ
Наследуемый класс не может выполнять поведение родителя, если родительский класс объявлен как sealed или final (в Kotlin/Java соответственно), что запрещает наследование. Также если родительский класс имеет приватные методы/поля, дочерний класс не сможет их переопределить или использовать напрямую.
Пример с final классом в Java:
final class Parent {
void doSomething() {
System.out.println("Parent action");
}
}
// Ошибка компиляции - нельзя наследовать final класс
class Child extends Parent {
@Override
void doSomething() {
System.out.println("Child action");
}
}
В Kotlin аналогично с sealed классом:
sealed class Parent {
open fun doSomething() { println("Parent") }
}
// Ошибка - разрешены только классы внутри sealed класса
class Child : Parent() {
override fun doSomething() { println("Child") }
} Ответ 18+ 🔞
А, ну это вообще классика, ёпта! Смотри, тут всё просто, как три копейки. Есть такая штука — наследование, да? Ну, типа, сынок хочет от папы что-то перенять, переделать под себя. Но иногда папа такой строгий, что говорит: "Нет, сынок, нахуй, будешь делать только так, как я сказал".
Вот это как раз про final в Java и sealed в Kotlin. Это такие волшебные слова, которые ставят на классе огромный амбарный замок и говорят: "Наследование закрыто, блядь!". Доверия ебать ноль к потенциальным наследникам.
Представь, ты написал идеальный класс, он делает всё чётко, без багов. А потом приходит какой-нибудь распиздяй, наследуется от него, и в своём методе doSomething() вместо полезной работы начинает майнить крипту. И твой красивый, отлаженный код превращается в пиздопроебибну. Чтобы такого не было, класс и делают final или sealed. "Сиди, сынок, и не рыпайся, будешь делать только так, как я задумал".
Вот смотри на пример, прям волнение ебать, как наглядно:
final class Parent {
void doSomething() {
System.out.println("Parent action");
}
}
// Ошибка компиляции - нельзя наследовать final класс
class Child extends Parent {
@Override
void doSomething() {
System.out.println("Child action");
}
}
Компилятор посмотрит на это и скажет: "Чувак, ты чё, охренел? Класс Parent же final! На каком хуя ты от него наследуешься? Иди отсюда, блядь". И красным подчеркнёт, и не скомпилирует ни за что.
В Kotlin та же фигня, только слово другое — sealed. Оно, правда, чуть хитрее. Оно не просто запрещает наследование где попало, а говорит: "Все мои дети должны быть перечислены прямо тут, рядом со мной, в одном файле". Как будто строгий отец собрал всех отпрысков в одной комнате и не выпускает на улицу.
sealed class Parent {
open fun doSomething() { println("Parent") }
}
// Ошибка - разрешены только классы внутри sealed класса
class Child : Parent() {
override fun doSomething() { println("Child") }
}
Опять компилятор встанет в позу: "Э, сабака сука! Ты куда лезешь? Кто тебя, Child, сюда звал? Все наследники Parent должны быть объявлены внутри его файла! Шёл бы ты на хуй со своим наследованием".
И про приватные методы/поля — это вообще отдельная песня. Это как если бы у папы был сейф в кабинете. Сынок может знать, что он есть, но комбинацию от него не знает, и папа ему её не скажет. Какой бы хороший сын ни был, до содержимого сейфа ему не добраться. Так и приватные члены класса — они только для внутренней кухни, наследникам туда ходу нет, хоть тресни.
Короче, смысл в том, чтобы контролировать бардак. Чтобы твой красивый замысел не разнесли в хлам какие-нибудь левые наследники, которые "ой, а я тут думал переопределить метод, а получилась хиросима". Вот для этого и ставят эти блокировки. Удивление пиздец, но иногда это очень полезно.