0Pricing
Swift Academy · Урок

Протоколы как контракты

Определяйте контракты поведения независимо от типов.

«Протоколы как контракты» — бесплатный урок Swift Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 4 уроков всего.

Что такое протокол

Протокол определяет набор методов, свойств и других требований, которые должен реализовать соответствующий тип. Это контракт: любой тип, принимающий протокол, обязуется предоставить всё, что в нём объявлено.

protocol Greetable {
    var name: String { get }
    func greet() -> String
}

Соответствие протоколу

Тип соответствует протоколу, принимая его и предоставляя каждое требование. Здесь структура реализует и свойство name, и метод greet().

protocol Greetable {
    var name: String { get }
    func greet() -> String
}

struct Person: Greetable {
    let name: String
    func greet() -> String { "Hello, I am " + name }
}

let p = Person(name: "Ada")
print(p.greet())

Требования к свойствам

Протоколы указывают, должно ли свойство быть доступно для чтения ({ get }) или для чтения и записи ({ get set }). Сохранённое или вычисляемое свойство может удовлетворить требованию только для чтения.

protocol Identifiable {
    var id: String { get }
}

struct User: Identifiable {
    let id: String
}

print(User(id: "u-1").id)

Требования к методам

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

protocol Shape {
    func area() -> Double
}

struct Square: Shape {
    let side: Double
    func area() -> Double { side * side }
}

print(Square(side: 3).area())

Требования к изменяющим методам

Для типов-значений методы, изменяющие self, должны быть отмечены как mutating. Объявляйте требование с помощью mutating, чтобы структуры могли ему соответствовать.

protocol Toggleable {
    mutating func toggle()
}

struct Switch: Toggleable {
    var isOn = false
    mutating func toggle() { isOn.toggle() }
}

var s = Switch()
s.toggle()
print(s.isOn)

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

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

protocol Animal { func sound() -> String }
struct Dog: Animal { func sound() -> String { "Woof" } }
struct Cat: Animal { func sound() -> String { "Meow" } }

let animals: [Animal] = [Dog(), Cat()]
for a in animals { print(a.sound()) }

Полиморфизм через протоколы

Вызов метода протокола передаёт управление конкретному типу, который скрывается за значением. Это позволяет писать код, работающий с множеством типов через единый контракт.

protocol Describable { func describe() -> String }
struct Book: Describable { let t: String; func describe() -> String { "Book: " + t } }
struct Film: Describable { let t: String; func describe() -> String { "Film: " + t } }

func show(_ d: Describable) { print(d.describe()) }
show(Book(t: "Swift"))
show(Film(t: "Inception"))

Требования к инициализаторам

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

protocol FromInt {
    init(value: Int)
}

struct Wrapper: FromInt {
    let value: Int
    init(value: Int) { self.value = value }
}

print(Wrapper(value: 42).value)

Наследование протоколов

Протокол может наследовать один или несколько других протоколов, добавляя дополнительные требования к унаследованным.

protocol Named { var name: String { get } }
protocol Aged: Named { var age: Int { get } }

struct Member: Aged {
    let name: String
    let age: Int
}

let m = Member(name: "Lin", age: 30)
print(m.name, m.age)

Протоколы только для классов

Пометьте протокол с помощью AnyObject, чтобы ограничить соответствие классами. Это полезно для требований со ссылочной семантикой, например для делегирования.

protocol Counter: AnyObject {
    var count: Int { get set }
}

class Box: Counter {
    var count = 0
}

let b = Box()
b.count = 5
print(b.count)

Проверка соответствия

Используйте is и as?, чтобы во время выполнения проверить, соответствует ли значение протоколу.

protocol Flyer { func fly() }
struct Bird: Flyer { func fly() { print("flap") } }
struct Rock {}

let things: [Any] = [Bird(), Rock()]
for t in things {
    if let f = t as? Flyer { f.fly() } else { print("grounded") }
}

Быстрая проверка

Проверьте своё понимание требований протоколов.

Итоги

Вы узнали, что протокол — это контракт: он объявляет требования к свойствам, методам, изменяющим методам и инициализаторам без реализаций. Типы соответствуют протоколу, выполняя каждое требование; протоколы можно использовать как типы для полиморфизма, они могут наследовать другие протоколы, а также ограничиваться классами с помощью AnyObject.

Часто задаваемые вопросы

Урок «Протоколы как контракты» бесплатный?

Да — полный текст урока «Протоколы как контракты» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 4 уроков всего.

Чему я научусь в уроке «Протоколы как контракты»?

Определяйте контракты поведения независимо от типов. Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Swift Academy?

Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Протоколы как контракты»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Swift Academy?

Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Протоколы как контракты
  2. Реализации по умолчанию в расширениях
  3. Композиция протоколов
  4. Условное соответствие протоколу
← Назад к Swift Academy