Understanding Protocols in Swift

A portrait painting style image of a pirate holding an iPhone.

by The Captain

on
April 14, 2024
Working with Protocols in Swift

Working with Protocols in Swift

Protocols in Swift are a powerful feature that allows you to define a blueprint of methods, properties, and other requirements that a class, structure, or enumeration must conform to. They enable you to create flexible and reusable code by defining a set of rules that types can adhere to.

Defining a Protocol

To define a protocol in Swift, you use the protocol keyword followed by the protocol's name. You can declare methods, properties, and associated types that conforming types must implement:

protocol Drawable {
    func draw()
    var color: String { get set }
}

Conforming to a Protocol

To conform to a protocol, a class, structure, or enumeration must implement all the required methods and properties defined in the protocol. Here's an example of a class conforming to the Drawable protocol:

class Circle: Drawable {
    var color: String = "Red"
    
    func draw() {
        print("Drawing a circle in \(color) color")
    }
}

Using Protocol Composition

In Swift, you can combine multiple protocols using protocol composition to create a more specific set of requirements. Protocol composition is achieved by separating the protocols with an ampersand (&):

protocol Shape {
    func area() -> Double
}

protocol Movable {
    func move(to point: (x: Double, y: Double))
}

protocol Drawable {
    func draw()
}

protocol DrawableShape: Shape, Movable, Drawable {
}

Protocol Inheritance

Protocols can also inherit from other protocols to build on existing requirements or add new ones. Sub-protocols inherit all the requirements from their parent protocols:

protocol Printable {
    func printDetails()
}

protocol Drawable: Printable {
    func draw()
}

Working with protocols in Swift allows you to create flexible and extensible code that promotes code reuse and maintainability. By defining protocols and enforcing their implementation, you can ensure that your types adhere to a common set of rules, making your code more robust and scalable.