Как в Swift добавить собственный инициализатор для структуры, сохранив memberwise инициализатор?

«Как в Swift добавить собственный инициализатор для структуры, сохранив memberwise инициализатор?» — вопрос из категории Swift Core, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

1. Определение кастомного инициализатора в extension Так как memberwise инициализатор не переопределяется в extension, он остаётся доступным.

struct Person {
    var name: String
    var age: Int
}

extension Person {
    init(name: String) {
        // Вызываем автоматически сгенерированный инициализатор
        self.init(name: name, age: 0)
    }
}

// Оба инициализатора доступны:
let person1 = Person(name: "Alex", age: 30) // Memberwise init
let person2 = Person(name: "Anna")          // Custom init (age = 0)

2. Использование значения по умолчанию для параметра Это самый простой способ, если нужно лишь задать значение по умолчанию для одного из свойств.

struct Person {
    var name: String
    var age: Int = 0 // Значение по умолчанию
}

// Можно использовать оба варианта:
let person1 = Person(name: "Alex", age: 30)
let person2 = Person(name: "Anna") // age автоматически равен 0

Важно: Для классов memberwise инициализатор не генерируется. Чтобы сохранить designated инициализатор и добавить convenience, используйте ключевое слово convenience.

class Vehicle {
    var wheels: Int

    init(wheels: Int) {
        self.wheels = wheels
    }

    convenience init() {
        self.init(wheels: 4) // Вызывает designated инициализатор
    }
}