Является ли open-класс в Swift final по умолчанию?

Ответ

Нет. Ключевое слово open и ключевое слово final в Swift являются взаимоисключающими.

  • open — это самый открытый уровень доступа для классов. Он явно разрешает:
    1. Наследование от этого класса в любом модуле.
    2. Переопределение его методов и свойств в любом модуле.
  • final — запрещает наследование от класса полностью. Его нельзя комбинировать с open.

Практическое правило: Если класс объявлен как open, он специально предназначен для наследования. Чтобы сделать open-класс неизменяемым, нужно явно пометить его как final, но тогда он перестанет быть open.

Пример:

// Этот класс МОЖНО наследовать в других модулях.
open class NetworkService {
    // Этот метод МОЖНО переопределить в других модулях.
    open func fetchData() { /* ... */ }

    // Этот метод НЕЛЬЗЯ переопределить нигде.
    public final func performRequest() { /* ... */ }
}

// Этот класс НЕЛЬЗЯ наследовать.
final class MyFinalUtility { /* ... */ }
// Ошибка компиляции: нельзя объявить 'open final' class
// open final class InvalidClass { }

Иерархия доступов для наследования (от наиболее открытого к закрытому): open > public (наследование только внутри модуля) > internal (по умолчанию) > final.

Ответ 18+ 🔞

А, слушай, тут один момент, который вгоняет в ступор новичков, а потом они такие: "чё за хуйня, компилятор ругается!". Так вот, запомни раз и навсегда, как отче наш: open и final — это как огонь и вода, ёпта. Они вместе не живут, они друг друга нахуй посылают.

Потому что суть у них прямо противоположная, блядь:

  • open — это как широко распахнутая дверь с вывеской "Добро пожаловать, наследуйте меня, где хотите, хоть в соседнем проекте! Переопределяйте мои методы, творите, выёбывайтесь!". Самый высший уровень гостеприимства для класса.
  • final — это, блядь, бетонная стена, сварная дверь и табличка "Наследование запрещено. Пошёл нахуй". Точка. Класс — монастырь, и в него не пускают.

И как ты, интересно, совместишь гостеприимство с "пошёл нахуй"? Правильно, никак. Компилятор тебе сразу в ебло ошибкой кинет.

Простое правило, которое спасёт тебе кучу нервов: Если класс open — он специально создан, чтобы от него плодились наследники. Хочешь его "закрыть"? Так объяви его просто public или internal, зачем он тогда open? А если хочешь сделать open-класс, но чтоб какие-то его куски не трогали — помечай отдельные методы как final.

Смотри, как на практике:

// Этот класс — публичный дом для всех желающих стать его потомком.
open class ВселенскийПоставщикДанных {
    // Этот метод — пожалуйста, переопределяй на здоровье в своём модуле.
    open func загрузитьВсё() { /* ... */ }

    // А вот этот метод — священная корова, тронешь — получишь по рукам. Он final.
    public final func выполнитьСвященныйЗапрос() { /* ... */ }
}

// А этот класс — затворник. От него наследоваться нельзя. Вообще.
final class МойЛичныйХелпер { /* ... */ }

// И вот это — НЕРАБОТАЮЩИЙ БРЕД, который вызовет у компилятора приступ хохота.
// open final class БесполезнаяХуйня { } // ОШИБКА: 'open' is incompatible with 'final'

Иерархия открытости для наследования, от самого щедрого до самого жадного, выглядит так: open (всем всё можно) > public (можно, но только внутри своего модуля) > internal (по умолчанию, только в своей папке) > final (НИКОМУ НИЧЕГО НЕЛЬЗЯ, ИДИ НАХУЙ).

Вот и вся магия, блядь. Не усложняй.