Видеокурсы по изучению языка программирования Swift. Подробнее

Добавление соответствия протоколу через расширение

Если вы нашли опечатку в тексте, выделите ее и нажмите CTRL + ENTER.

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

Заметка

Существующие экземпляры типа автоматически принимают и отвечают требованиям протокола, когда опции, необходимые для соответствия добавляются через расширение типа.

К примеру, этот протокол TextRepresentable может быть реализован любым типом, который может отображать текст. Это может быть собственное описание или текстовая версия текущего состояния:

protocol TextRepresentable {
    func textualDescription() -> String
}

Класс Dice, о котором мы говорили ранее, может быть расширен для принятия и соответствия протоколу TextRepresentable:

extension Dice: TextRepresentable {
    func textualDescription() -> String {
        return "Игральная кость с \(sides) гранями"
    }
}

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

Теперь экземпляр Dice может быть использован как TextRepresetable:

let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
print(d12.textualDescription())
// Выведет "Игральная кость с 12 гранями"

Аналогично игровой класс SnakesAndLadders может быть расширен для того, чтобы смог принять и соответствовать протоколу TextRepresentable:

extension SnakesAndLadders: TextRepresentable {
    func textualDescription() -> String {
        return "Игра Змеи и Лестницы с полем в \(finalSquare) клеток"
    }
}
print(textualDescription())
// Выведет "Игра Змеи и Лестницы с полем в 25 клеток"

Принятие протокола через расширение

Если тип уже соответствует всем требованиям протоколу, но еще не заявил, что он принимает этот протокол, то вы можете сделать это через пустое расширение:

struct Hamster {
    var name: String
    func textualDescription() -> String {
        return "Хомяка назвали \(name)"
    }
}
extension Hamster: TextRepresentable {}

Экземпляры Hamster теперь могут быть использованы в тех случаях, когда нужен тип TextRepresentable:

let simonTheHamster = Hamster(name: "Фруша")
let somethingTextRepresentable: TextRepresentable = simonTheHamster
print(somethingTextRepresentable.textualDescription())
// Выведет "Хомяка назвали Фруша"

Заметка

Типы не принимают протоколы автоматически, если они удовлетворяют их требованиям. Принятие протокола должно быть объявлено в явной форме.

Swift: 
3.0