Ответ
В Kotlin классы по умолчанию final (не наследуемые) для соблюдения принципа "закрытости/открытости" (Open/Closed Principle) из SOLID. Это предотвращает случайное наследование и модификацию поведения класса без явного разрешения. Чтобы разрешить наследование, нужно явно пометить класс как open:
open class Parent // Теперь можно наследоваться
class Child : Parent() // ОК
class NotOpenParent // По умолчанию final
// class ErrorChild : NotOpenParent() // Ошибка: Cannot inherit from final class
Преимущества:
- Защита от неконтролируемого расширения
- Упрощение рефакторинга (меньше зависимостей)
- Явное проектирование иерархий через
open
Ответ 18+ 🔞
Давай разберёмся, что за фигня тут происходит с этими классами в Kotlin. Представь, что ты пришёл в гости, а тебе говорят: "Вот этот стул — сиди, а вот этот шкаф — не трогай, он закрыт". Примерно так же Kotlin относится к классам по умолчанию.
Ёпта, они все final! То есть, запечатаны нахуй. Нельзя просто так взять и отнаследоваться, как в том же Java, где каждый класс — потенциальная проходная дворовая, готовая к расширению. А всё почему? А потому что какой-то умный дядька по имени Роберт Мартин (не путать с Мартином из "Назад в будущее") придумал принцип под названием "закрыто/открыто". Суть в том, что класс должен быть закрыт для модификаций, но открыт для расширений. А чтобы его расширить, нужно явно сказать: "Чувак, я тебе доверяю, делай со мной что хочешь". Иначе — никаких неожиданных наследников, которые могут всё сломать.
Вот смотри, как это выглядит в коде. Если ничего не указать — это стена:
class NotOpenParent // По умолчанию final, типа "не лезь, убьёт"
// class ErrorChild : NotOpenParent() // Ошибка! Нельзя наследоваться от final класса. Сам от такого охуеешь.
Компилятор тебе сразу: "Cannot inherit from final class NotOpenParent". Доверия ебать ноль, сразу видно.
А если ты действительно планировал большую и счастливую семью классов, то нужно крикнуть волшебное слово open:
open class Parent // Всё, я открыт! Наследуйтесь на здоровье, дети мои.
class Child : Parent() // И вот уже ребёнок есть. Всё легально, без подвохов.
В чём, блядь, профит от такой строгости?
-
Защита от распиздяйства. Ты явно решаешь, какой класс можно расширять, а какой — нет. Никакой случайный коллега (или ты же через полгода) не нанаследует от твоего хитроумного
HttpClientкакую-нибудьMySuperHttpClientWithBlackjackAndHookersи не сломает всю логику. Подозрение ебать чувствую к таким неявным расширениям. -
Рефакторинг без сердечного приступа. Если класс
final, ты знаешь, что его поведение не переопределено в десяти других местах проекта. Можешь спокойно менять его внутренности, не боясь, что где-то в глубине системы упадёт переопределённый методdoSomethingCritical(). Это терпения ноль ебать экономит. -
Явность — наше всё. Глядя на код, сразу видно, что
open class— это точка расширения, проектировавшаяся для этого. А обычныйclass— это законченная, самодостаточная сущность. Архитектура становится читаемее. Не надо гадать, "какого хуя" этот класс вдруг унаследовали в другом модуле.
Короче, хуй с горы — это когда в Java всё открыто, и потом разбирайся, почему всё ломается. А в Kotlin подход "по умолчанию закрыто" — это как хороший замок на двери: не мешает жить, но от незваных гостей защищает. Сначала бесит, а потом понимаешь — охуенно же. Просто надо привыкнуть явно говорить open, когда это нужно.