Почему инициализатор, объявленный в протоколе, должен быть помечен как required в реализующем его классе?

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

Ответ

Требование required гарантирует, что все будущие подклассы данного класса также будут иметь этот инициализатор, обеспечивая полное и корректное соответствие протоколу на всём дереве наследования.

Причина: Протокол определяет контракт. Если класс A соответствует протоколу P, то любой экземпляр A (включая экземпляры его подклассов B, C) должен быть создаваемым через инициализатор из P. Без required подкласс мог бы не реализовать этот инициализатор, нарушив контракт протокола.

protocol Configurable {
    init(config: Configuration) // Требует инициализатор
}

class BaseViewController: UIViewController, Configurable {
    // required обязательно, чтобы подклассы тоже его реализовали
    required init(config: Configuration) {
        super.init(nibName: nil, bundle: nil)
        // ... настройка
    }

    required init?(coder: NSCoder) { /* ... */ }
}

class ProfileViewController: BaseViewController {
    // ProfileViewController НЕЯВНО наследует required init(config:)
    // и соответствует протоколу Configurable.
    // Если бы в BaseViewController не было `required`,
    // ProfileViewController мог бы не иметь этого инициализатора.
}

Исключение: Класс, помеченный как final, не может иметь подклассов, поэтому для него модификатор required можно опустить — требование протокола выполняется только на уровне этого класса.

final class Utility: Configurable {
    // `required` не нужно, так как наследования не будет
    init(config: Configuration) { /* ... */ }
}

Для структур (struct) и перечислений (enum) модификатор required не применяется, так как они не поддерживают наследование.