Что такое состав протокола?

Это процесс объединения нескольких протоколов в один протокол. Вы можете думать об этом как о множественном наследовании, за исключением протоколов.

Давайте посмотрим на некоторые примеры.

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

protocol CanDoDogThings {
    
    func bark()
    
    func waggTail()
    
}
struct Runner {
    
    let dog: CanDoDogThings
    
    func ballFound() {
        dog.waggTail()
        dog.bark()
    }
    
}

Это простая и удобная реализация, так как она четко определяет, что собака способна делать, когда мяч найден, вилять хвостом и лаять. Этот подход также можно легко протестировать, поскольку экземпляры можно имитировать. Однако по мере роста вашего приложения вы можете ввести больше зависимостей, таких как прыжки или еда. Таким образом, вы можете в конечном итоге написать одинаковый шаблонный код для каждого, что может привести к проблемам с обслуживанием, а никто из нас этого не хочет!

Что нам нужно, так это простота обслуживания, но при этом получение всех преимуществ прямого и прямого внедрения зависимостей.

Примем состав протокола.

protocol CanBark {
    func bark()
}
protocol CanWaggTail {
    func waggTail()
}
struct Dog {
    
    // Protocol Composition
    typealias Dependency = CanBark & CanWaggTail
    
    let dogManager: Dependency
    
    func ballFound() {
        dogManager.waggTail()
        dogManager.bark()
    }
    
}
/*----- Another Way! -----*/
// Protocol Composition
protocol CanDoDogThings: CanBark, CanWaggTail {
    
}
struct Dog {
    
    let dogManager: CanDoDogThings
    
    func ballFound() {
        dogManager.waggTail()
        dogManager.bark()
    }
}

Таким образом, композиция может быть выполнена по-разному.

Мне нравятся оба подхода, так как все зависимости теперь объединены, а не несколько непересекающихся протоколов:

  • Все зависимости теперь четко определены.
  • Единая точка входа верхнего уровня, чтобы управлять ими всеми 😅.
  • Компилятор может обеспечить реализацию полного протокола.
  • В целом он кажется более чистым и сплоченным.

Исследуйте реальный пример на здесь.