Протоколы
Одной из особенностей языка Swift являются протоколы. По сути — это интерфейсы, определяющие список свойств и методов, которые должны быть реализованы принимающими классами, структурам или перечислениями. Для выстраивания иерархии, протоколы поддерживают наследование, в том числе множественное. Также их разрешается использовать как типы; отличительной чертой служит возможность создавать типы-композиции через protocol<Protocol1, Protocol2, ..., ProtocolN>.
import UIKit
protocol Selectable {
var selected: Bool { get set }
func select()
func deselect()
}
protocol Colorable {
func paint()
}
// Shape protocol inherits Selectable and Colorable protocols
protocol Shape: Selectable, Colorable {
var type: String { get }
}
protocol Rounded {
var radius: Double { get set }
}
// Oval inherits UIView class and adopts protocols Rounded and Shape
class Oval: UIView, Rounded, Shape {
let type = "oval"
var radius = 10.0
var selected = false
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func select() {
selected = true
}
func deselect() {
selected = false
}
func paint() {
backgroundColor = UIColor.redColor()
}
}
class Squircle: UIView, Rounded, Shape {
let type = "squircle"
var radius = 3.0
var selected = false
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func select() {
selected = true
}
func deselect() {
selected = false
}
func paint() {
backgroundColor = UIColor.greenColor()
}
}
// Define composition protocol type
typealias RoundedShape = protocol<Rounded, Shape>
// Array initialization as [protocol<Rounded, Shape>]() doesn't work
var roundedShapes = [RoundedShape]()
roundedShapes.append(Oval())
roundedShapes.append(Squircle())
С выходом Swift 2.0 протоколы обзавелись расширениями. Они позволяют добавлять реализацию по умолчанию методов и свойств (новых или уже существующих). Если необходимо, область действия расширений ограничивается только нужными типами, делается это конструкцией where.
import UIKit
// Make Selectable protocol adoptable only by classes (not structs, enums)
protocol Selectable: class {
var selected: Bool { get set }
func select()
func deselect()
}
/*
Add default implementations of select() and deselect() protocol methods
and new toggleSelection() method only for UIView subclasses that adopt Selectable protocol
*/
extension Selectable where Self: UIView {
func select() {
selected = true
}
func deselect() {
selected = false
}
func toggleSelection() {
selected = !selected
}
}
class Shape: UIView, Selectable {
var selected = false
}
Встроенные протоколы тоже можно расширять.
import Foundation
extension BooleanType {
var trueReverse: Bool {
if self {
return !Bool(self)
} else {
return Bool(self)
}
}
}
print(true.trueReverse)
// Output: false
print(false.trueReverse)
// Output: false
Дополнительные материалы: