Может ли инициализатор в Swift возвращать опциональный экземпляр?

Ответ

Да, для этого используются Failable Initializers (проваливающиеся инициализаторы). Они помечаются знаком ? после init и возвращают опциональное значение типа Type?.

Синтаксис и пример:

struct Temperature {
    let celsius: Double

    // Проваливающийся инициализатор
    init?(celsius: Double) {
        guard celsius >= -273.15 else {
            return nil // Невозможно создать объект при температуре ниже абсолютного нуля
        }
        self.celsius = celsius
    }
}

let validTemp = Temperature(celsius: 25) // Temperature?
let invalidTemp = Temperature(celsius: -300) // nil

Ключевые моменты:

  1. Используйте init? для обозначения проваливающегося инициализатора.
  2. Возвращайте nil в случае неудачи (невалидные параметры, отсутствие ресурсов).
  3. Неявно разворачиваемый проваливающийся инициализатор (init!) существует, но его использование рискованно, так как при возврате nil приведет к крашу при обращении.

Практическое применение: Валидация входных данных, загрузка ресурсов (изображений, данных), декодирование.

Ответ 18+ 🔞

А, ну это ж про Failable Initializers, они же проваливающиеся инициализаторы! Суть в том, что они могут сказать: «Знаешь что, чувак? Я тут попробовал, но нихуя не вышло, держи nil». Помечаются они вопросительным знаком после init, вот так: init?.

Как это выглядит в коде, блядь:

struct Temperature {
    let celsius: Double

    // Вот он, красавец, проваливающийся инициализатор
    init?(celsius: Double) {
        guard celsius >= -273.15 else {
            return nil // Абсолютный ноль, ёпта! Ниже — физически нихуя невозможно
        }
        self.celsius = celsius
    }
}

let validTemp = Temperature(celsius: 25) // Temperature? — окей
let invalidTemp = Temperature(celsius: -300) // nil — потому что это пиздец какой холод

Что тут важно запомнить, чтобы не облажаться:

  1. Пишешь init? — и все сразу понимают, что тут может быть подвох.
  2. Если параметры кривые или ресурс не найден — просто возвращаешь nil, и все дела. Никаких плясок с бубном.
  3. Есть ещё вариант init! (неявно разворачиваемый), но это, блядь, как ходить по тонкому льду в одних трусах. Вернёт nil, а ты попробуй к нему обратиться — получишь краш в ебало. Лучше без фанатизма.

Где это реально пригождается, а не просто для понтов? Ну, например, проверяешь входящие данные (как с температурой), грузишь картинку из файла (а файла-то нет, сука!), или парсишь данные из сети — в общем, везде, где может случиться хуйня, а не результат.