Protocols in Swift Fast AF
Protocols are a powerful tool in the Swift programming language that allow developers to define a set of requirements that a class, structure, or enumeration must fulfill in order to be considered conforming to a particular protocol. In this tutorial, we will explore how protocols work in Swift and how they can be used to define reusable and modular code.
First, let’s define a simple protocol called Shape
that requires conforming types to have a area
property and a perimeter
method.
protocol Shape {
var area: Double { get }
func perimeter() -> Double
}
Now, let’s define a Circle
class that conforms to the Shape
protocol. To do this, we simply need to include the Shape
protocol in the class declaration and implement the required area
property and perimeter
method.
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
}
}
Now, any instance of the Circle
class will be considered a Shape
because it conforms to the Shape
protocol. We can verify this by creating an instance of Circle
and calling its area
and perimeter
methods.
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
Protocols can also have optional requirements, which are methods or properties that are not required for conformance but can be implemented by conforming types if desired. To define an optional requirement, we simply need to include the optional
keyword before the method or property declaration.
Let’s add an optional description
property to the Shape
protocol.
protocol Shape {
var area: Double { get }
func perimeter() -> Double
var description: String { get }
}
Now, let’s update the Circle
class to implement the optional description
property.
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
}
}
We can now call the description
property on our circle
instance to see the implementation of the optional requirement.
let circle = Circle(radius: 5)
print(circle.description) // Circle with radius: 5
Protocols can also be extended to provide default implementations for optional requirements or to add additional functionality to conforming types. Let’s extend the Shape
protocol to add a default implementation for the description
property.
extension Shape {
var description: String {
return "Unidentified shape"
}
}
Now, if a class does not implement the description
property, it will automatically use the default implementation provided by the extension.
In conclusion, protocols are a useful tool in Swift that allow developers to define a set of requirements that a class, structure, or enumeration must fulfill in order to be considered conforming to a particular protocol. Protocols can also have optional requirements and can be extended to provide default implementations or additional functionality for conforming types. Protocols allow for the creation of reusable and modular code and can be an important part of any Swift project.
References:
- Apple Inc. (n.d.). Protocols. Retrieved from https://docs.swift.org/swift-book/LanguageGuide/Protocols.html
- Apple Inc. (n.d.). Protocol Extensions. Retrieved from https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID465