protocols
In Swift, protocols define a blueprint of methods, properties, and other requirements for a particular task or piece of functionality. Protocols can be adopted by classes, structures, and enumerations to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol.
Basic Protocol Syntax
Here's a simple example defining a protocol with a single instance method requirement:
protocol Animal {
func makeSound()
}
Adopting Protocols
A class, structure, or enumeration can adopt one or more protocols, separated by commas, and provide the actual implementation for the requirements of those protocols.
class Dog: Animal {
func makeSound() {
print("Woof, woof!")
}
}
struct Cat: Animal {
func makeSound() {
print("Meow!")
}
}
Protocol Properties
Protocols can require that conforming types have specific instance properties or type properties with a particular name and type.
protocol Named {
var name: String { get }
}
Here, the Named protocol requires a read-only property name of type String.
Protocol Methods
You can define both instance and type methods as part of a protocol’s definition.
protocol RandomNumberGenerator {
func random() -> Double
}
Optional Requirements
Swift protocols can have optional requirements, which are prefixed by the optional keyword. Note that this feature requires the protocol to be marked with the @objc attribute
@objc protocol OptionalProtocol {
@objc optional func optionalMethod()
}
Protocol Composition
Swift allows you to combine multiple protocols together. This is known as protocol composition.
protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
struct Person: Named, Aged {
var name: String
var age: Int
}
func wishHappyBirthday(to celebrator: Named & Aged) {
print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}
Protocol Inheritance
A protocol can inherit from one or more other protocols and can add further requirements on top of the requirements it inherits.
protocol Movable {
func move()
}
protocol Drivable: Movable {
func startEngine()
}
Protocol Extensions
Protocols can be extended to provide method and property implementations to conforming types. This allows you to define behavior on protocols themselves, rather than in each type’s individual conformance.
extension Animal {
func makeSound() {
print("Some generic animal sound.")
}
}
Now, types conforming to Animal can have a default makeSound implementation.
Protocols as Type
Protocols can be used as types, which is a powerful feature in Swift that can be used in various situations like parameter types, return types, and array types.
func perform(animal: Animal) {
animal.makeSound()
}
let myDog: Animal = Dog()
let myCat: Animal = Cat()
perform(animal: myDog) // Output: Woof, woof!
perform(animal: myCat) // Output: Meow!
Protocols are a fundamental tool in Swift that help you write flexible and reusable code. They are especially important in writing generic code and implementing design patterns like the delegate pattern, the strategy pattern, etc.