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

Протоколы как типы

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

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

Так как это тип, то вы можете использовать протокол во многих местах, где можно использовать другие типы:

  • Как тип параметра или возвращаемый тип в функции, методе, инициализаторе
  • Как тип константы, переменной или свойства
  • Как тип элементов массива, словаря или другого контейнера

Заметка

Из-за того что протоколы являются типами, то их имена начинаются с заглавной буквы (как в случае FullyNamed или RandomNumberGenerator) для соответствия имен с другими типами Swift (Int, String, Bool, Double…)

Вот пример использования протокола в качестве типа:

class Dice {
    let sides: Int
    let generator: RandomNumberGenerator
    init(sides: Int, generator: RandomNumberGenerator) {
        self.sides = sides
        self.generator = generator
    }
    func roll() -> Int {
        return Int(generator.random() * Double(sides)) + 1
    }
}

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

Свойство generator имеет тип RandomNumberGenerator, таким образом вы можете использовать в этом свойстве экземпляр любого типа, соответствующий протоколу RandomNumberGenerator. Больше ничего не требуется от экземпляра, присваемого этому свойству, кроме того, что этот экземпляр должен принимать протокол RandomNumberGenerator.

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

Dice предоставляет один метод экземпляра - roll, который возвращает целое значение от 1 и до количества сторон на игральной кости. Этот метод вызывает генератор метода random(), для создания нового случайного числа от 0.0 и до 1.0, а затем использует это случайное число для создания значения броска игральной кости в соответствующем диапазоне (1…n). Так как мы знаем, что generator принимает RandomNumberGenerator, то это гарантирует нам, что у нас будет метод random().

Вот как используется класс Dice для создания шестигранный игральной кости с экземпляром LinearCongruentialGenerator в качестве генератора случайных чисел:

var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
for _ in 1...5 {
    print("Бросок игральной кости \(d6.roll())")
}
// Бросок игральной кости равен 3
// Бросок игральной кости равен 5
// Бросок игральной кости равен 4
// Бросок игральной кости равен 5
// Бросок игральной кости равен 4

 

Swift: 
4.0