Какие инициализаторы можно добавлять в extension в Swift?

Ответ

Для классов:

В extension класса можно добавлять только convenience-инициализаторы:

class Person {
    let name: String
    let age: Int

    // Designated инициализатор - только в основном объявлении
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

extension Person {
    // Convenience инициализатор - можно в extension
    convenience init(name: String) {
        self.init(name: name, age: 0)
    }

    // Еще один convenience инициализатор
    convenience init() {
        self.init(name: "Unknown", age: 0)
    }
}

Для структур и перечислений:

Можно добавлять любые инициализаторы, так как у них нет наследования:

struct Point {
    var x: Double
    var y: Double
}

extension Point {
    // Можно добавить designated инициализатор для структуры
    init(value: Double) {
        self.x = value
        self.y = value
    }
}

enum CompassDirection {
    case north, south, east, west
}

extension CompassDirection {
    // Инициализатор для enum
    init(from string: String) {
        switch string.lowercased() {
        case "n": self = .north
        case "s": self = .south
        // ...
        default: self = .north
        }
    }
}

Ограничения для extension классов:

  1. Нельзя добавлять designated инициализаторы
  2. Нельзя добавлять required инициализаторы
  3. Нельзя добавлять deinitializer
  4. Нельзя добавлять инициализаторы, если класс помечен как @frozen

Практический пример с UIKit:

extension UIViewController {
    // Convenience инициализатор для UIViewController
    convenience init(nibName: String? = nil) {
        self.init(nibName: nibName, bundle: nil)
    }
}

Рекомендации:

  • Используйте extension для добавления convenience инициализаторов, которые предоставляют значения по умолчанию
  • Добавляйте инициализаторы в extension для лучшей организации кода
  • Помните, что required инициализаторы должны быть в основном объявлении класса

Ответ 18+ 🔞

А, ну это про инициализаторы в экстеншенах! Ёпта, тема-то какая хитрая, как жопа с замочной скважиной. Слушай, сейчас разжую, как мартышке банан.

Вот смотри, с классами тут отдельная песня, пиздец. В экстеншен к классу ты можешь пихать только convenience-инициализаторы. Designated — нихуя, только в основном теле класса. Это как закон: основную дверь (designated) ставишь при стройке дома, а дополнительные калиточки (convenience) уже можешь приделать потом, на участке (в extension).

class Person {
    let name: String
    let age: Int

    // Вот это твой главный, designated инициализатор. Его место тут, в святая святых.
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

extension Person {
    // А это уже convenience — пожалуйста, хуячь в extension, никто не запретит.
    convenience init(name: String) {
        self.init(name: name, age: 0) // Обязательно зовёт designated
    }

    // И вот этот тоже можно, ебать его в сраку.
    convenience init() {
        self.init(name: "Unknown", age: 0)
    }
}

А вот для структур и энамов — полная свобода, волнение ебать! У них наследования нет, поэтому им похуй. Хочешь — designated инициализатор в экстеншен? Да хуярь!

struct Point {
    var x: Double
    var y: Double
}

extension Point {
    // Для структуры — да хоть designated, да хоть на ушах стой. Можно.
    init(value: Double) {
        self.x = value
        self.y = value
    }
}

Главные запреты для классов, блядь:

  1. Designated инициализаторы — нихуя. Только в основном теле.
  2. Required инициализаторы — тоже нихуя. Тоже только в основном теле.
  3. Деинициализатор (deinit) — забудь, как страшный сон. Его место только в классе.
  4. Если класс @frozen — тогда ваще нихуя нельзя, сиди и не рыпайся.

Практический пример, чтобы не быть мудаком:

extension UIViewController {
    // Convenience — значит, можно. Удобная калиточка.
    convenience init(nibName: String? = nil) {
        self.init(nibName: nibName, bundle: nil)
    }
}

Итог, чувак:
Хочешь добавить инициализатор с дефолтными значениями, чтобы не писать одно и то же сто раз? Засовывай convenience init в extension — это канон. Организация кода будет огонь, а не пиздец. Но про required и designated — даже не думай, там тебе сразу компилятор впендюрит ошибку. Всё, рот меня чих-пых, вопрос закрыт.