Можно ли в Swift extension протокола добавить соответствие другому протоколу?

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

Ответ

Да, можно. Это мощная техника для добавления требований протокола и реализации по умолчанию через условные расширения.

1. Добавление соответствия протоколу с реализацией по умолчанию

protocol Displayable {
    var displayName: String { get }
}

protocol Identifiable {
    var id: UUID { get }
}

// Расширяем Identifiable, добавляя соответствие Displayable
// только для типов, которые уже соответствуют Identifiable
extension Identifiable {
    var displayName: String {
        return "ID: (id.uuidString.prefix(8))"
    }
}

// Теперь любой тип, соответствующий Identifiable,
// автоматически получает реализацию Displayable
struct User: Identifiable {
    let id = UUID()
    // displayName доступен автоматически
}

let user = User()
print(user.displayName) // "ID: A1B2C3D4"

2. Условные расширения с where-ограничениями

protocol Savable {
    func save()
}

// Добавляем соответствие Savable только для Collection,
// элементы которой соответствуют Codable
extension Collection where Element: Codable {
    func save() {
        let encoder = JSONEncoder()
        if let data = try? encoder.encode(self) {
            // Сохранение данных
            UserDefaults.standard.set(data, forKey: "collection")
        }
    }
}

// Теперь массив Codable объектов получает метод save()
struct Item: Codable {}
let items: [Item] = [Item(), Item()]
items.save() // Работает!

Ключевые преимущества:

  • Повышение переиспользуемости кода
  • Избегание дублирования реализации
  • Точечное добавление функциональности только нужным типам
  • Поддержка протокол-ориентированного дизайна