Почему Swift не генерирует memberwise инициализатор для классов?

Ответ

Swift не генерирует автоматический memberwise инициализатор для классов из-за их наследуемой природы и требований безопасности инициализации.

Основные причины:

  1. Наследование — класс должен гарантировать корректную инициализацию не только своих свойств, но и унаследованных от суперкласса.
  2. Безопасность — компилятор требует явного контроля над процессом инициализации для предотвращения частично инициализированных объектов.
  3. Гибкость — классы могут иметь вычисляемые свойства, наблюдатели или требовать дополнительной логики при инициализации.

Три способа обеспечить инициализацию класса:

  1. Назначение значений по умолчанию всем stored-свойствам
  2. Реализация собственного инициализатора
  3. Наследование инициализатора от суперкласса

Пример:

class Person {
    var name: String
    var age: Int

    // Должны написать явно — Swift не сгенерирует init(name:age:)
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

// Для сравнения — структура получает memberwise инициализатор автоматически
struct Point {
    var x: Double
    var y: Double
    // Имеет init(x:y:) по умолчанию
}

Контраст со структурами: Структуры получают memberwise инициализатор, так как они не поддерживают наследование и имеют более простую семантику копирования.

Ответ 18+ 🔞

Ага, слушай, вот это вообще классика, блядь! Сидишь такой, переписываешь код со структуры на класс, и тут — пиздец! Куда делся мой красивый init(name: age:)? А его нет, сука!

Swift, этот хитрожопый компилятор, просто берёт и НЕ ГЕНЕРИРУЕТ автоматический инициализатор для классов. Вообще. Ни хуя. А знаешь почему? Ну, держись.

Вот нахуй так происходит:

  1. Наследование, блядь! Это же не какая-то тупая структура, которая сама по себе. Класс — он может от кого-то родиться. И компилятору надо быть на 146% уверенным, что когда ты создаёшь объект, там всё проинициализировано правильно: и твои свеженаписанные свойства, и всё, что там наворочено у родителя. А автоматический инициализатор про это нихуя не знает, вот его и нет.

  2. Безопасность, ёпта! Чтобы не получилось так, что у тебя объект уже в памяти болтается, а половина свойств в нём — nil или какая-то хуйня. Swift не любит неопределённость, как кот лоток грязный.

  3. Гибкость, вротберунчик! В классе же может быть не просто var name: String. Там может быть вычисляемое свойство, там могут быть наблюдатели didSet, которые при инициализации нахуй не нужны, или тебе перед сохранением значения надо его через сито пропустить. Куда это впихнуть в автосгенерированный инит?

Ну и что делать-то, если очень хочется? Варианты, как всегда, есть:

  1. По-дедовски: Всем свойствам значения по умолчанию присвоить. var name: String = "". Готово, можно Person() создавать. Но это, бля, не всегда окей.
  2. Взять и написать самому, блядь! Да, вот так вот, руками. Как взрослый. Объявляешь init(name: String, age: Int) и внутри раздаёшь self.name = name. Скучно, зато надёжно.
  3. Наследовать от предка. Если у родительского класса есть подходящий init, и ты все свои свойства по дефолту проинициализировал — можешь его унаследовать.

Смотри, вот тебе наглядный пиздец, прости, пример:

class Person {
    var name: String
    var age: Int

    // Бля, придётся это писать САМОМУ! Swift за тебя это не сделает, ленивая жопа!
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

// А теперь смотри на эту мартышку-структуру! Ей всё похуй!
struct Point {
    var x: Double
    var y: Double
    // А здесь init(x:y:) УЖЕ ЕСТЬ, ПОДАРОЧКОМ! Бесплатно, сука!
    // Потому что структура — она простая, без этих ваших наследований.
}

Вот и весь сказ, блядь. Классы — они сложные, ответственные. За них надо думать. А структуры — как весёлые туристы, им всё включено. Выбирай, что тебе больше по душе: власть и ответственность или бесплатный сыр, понимаешь?