Протоколы — это мощный инструмент языка программирования Swift, который позволяет разработчикам определять набор требований, которым должен соответствовать класс, структура или перечисление, чтобы считаться соответствующими конкретному протоколу. В этом руководстве мы рассмотрим, как протоколы работают в Swift и как их можно использовать для определения повторно используемого и модульного кода.
Во-первых, давайте определим простой протокол с именем Shape
, который требует, чтобы соответствующие типы имели свойство area
и метод perimeter
.
protocol Shape { var area: Double { get } func perimeter() -> Double }
Теперь давайте определим класс Circle
, соответствующий протоколу Shape
. Для этого нам просто нужно включить протокол Shape
в объявление класса и реализовать требуемое свойство area
и метод perimeter
.
class Circle: Shape { let radius: Double var area: Double { return .pi * radius * radius } func perimeter() -> Double { return 2 * .pi * radius } init(radius: Double) { self.radius = radius } }
Теперь любой экземпляр класса Circle
будет считаться Shape
, поскольку он соответствует протоколу Shape
. Мы можем проверить это, создав экземпляр Circle
и вызвав его методы area
и perimeter
.
let circle = Circle(radius: 5) print(circle.area) // 78.53981633974483 print(circle.perimeter()) // 31.41592653589793 let circle = Circle(radius: 5) print(circle.area) // 78.53981633974483 print(circle.perimeter()) // 31.41592653589793
Протоколы также могут иметь необязательные требования, то есть методы или свойства, которые не требуются для соответствия, но при желании могут быть реализованы с помощью соответствующих типов. Чтобы определить необязательное требование, нам просто нужно включить ключевое слово optional
перед объявлением метода или свойства.
Давайте добавим необязательное свойство description
в протокол Shape
.
protocol Shape { var area: Double { get } func perimeter() -> Double var description: String { get } }
Теперь давайте обновим класс Circle
, чтобы реализовать необязательное свойство description
.
class Circle: Shape { let radius: Double var area: Double { return .pi * radius * radius } func perimeter() -> Double { return 2 * .pi * radius } var description: String { return "Circle with radius: \(radius)" } init(radius: Double) { self.radius = radius } }
Теперь мы можем вызвать свойство description
в нашем экземпляре circle
, чтобы увидеть реализацию необязательного требования.
let circle = Circle(radius: 5) print(circle.description) // Circle with radius: 5
Протоколы также могут быть расширены для предоставления реализации по умолчанию для дополнительных требований или для добавления дополнительных функций к соответствующим типам. Давайте расширим протокол Shape
, чтобы добавить реализацию по умолчанию для свойства description
.
extension Shape { var description: String { return "Unidentified shape" } }
Теперь, если класс не реализует свойство description
, он будет автоматически использовать реализацию по умолчанию, предоставляемую расширением.
В заключение, протоколы — это полезный инструмент в Swift, который позволяет разработчикам определять набор требований, которым должен соответствовать класс, структура или перечисление, чтобы считаться соответствующими конкретному протоколу. Протоколы также могут иметь необязательные требования и могут быть расширены для обеспечения реализации по умолчанию или дополнительных функций для соответствующих типов. Протоколы позволяют создавать многоразовый и модульный код и могут быть важной частью любого проекта Swift.
Использованная литература:
- Apple Inc. (без даты). Протоколы. Получено с https://docs.swift.org/swift-book/LanguageGuide/Protocols.html
- Apple Inc. (без даты). Расширения протокола. Получено с https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID465