Model your program

Swift Protocols

Learn how protocols work in Swift to give different types a shared set of properties and methods, and how a struct or class adopts and conforms to them.

This tutorial belongs to the Swift series

A protocol is a contract. It lists properties and methods, and any type that signs the contract promises to provide them. This is how objects of different types, structs and classes alike, end up sharing a common set of functionality.

You define a protocol with the protocol keyword:

protocol Mammal {

}

Structs and classes adopt a protocol by listing it after a colon:

struct Dog: Mammal {

}

class Cat: Mammal {

}

Requirements

An empty protocol doesn’t ask for anything. A useful one lists properties and methods, without values and without implementations:

protocol Mammal {
    var age: Int { get set }
    func walk()
}

A property requirement says how it must be accessible. { get set } means readable and writable. { get } means the type only has to make it readable, and can still choose to make it writable.

Any type that adopts the protocol must conform to it by providing those properties and methods:

struct Dog: Mammal {
    var age: Int = 0
    func walk() {
        print("The dog is walking")
    }
}

class Cat: Mammal {
    var age: Int = 0
    func walk() {
        print("The cat is walking")
    }
}

Forget one requirement and the code doesn’t compile. Remove walk() from Dog and the compiler says Type 'Dog' does not conform to protocol 'Mammal', and Xcode offers to add the missing method for you. This is the compiler doing your checklist.

Using the protocol as a type

Here’s where protocols pay off. You can use Mammal as a type, and any conforming value fits:

let animals: [Mammal] = [Dog(), Cat()]

for animal in animals {
    animal.walk()
}
// The dog is walking
// The cat is walking

Dog is a struct and Cat is a class, and they still live in the same array. The loop only knows it has mammals, and it only calls what the protocol promises. Each value runs its own version of walk().

Adopting multiple protocols

A type can adopt several protocols, separated by commas:

protocol Animal {
    var name: String { get }
}

struct Dog: Mammal, Animal {
    var age: Int = 0
    var name = "Roger"
    func walk() {
        print("The dog is walking")
    }
}

Now Dog must satisfy both contracts.

Notice that for classes, this is the same syntax used to declare a superclass. If there is a superclass, list it first, right after the colon, and the protocols after it. In class Beagle: Dog, Mammal, Dog would be the superclass and Mammal a protocol. Swift knows which is which because a class can only inherit from one class.

Protocols are a big topic in Swift. The standard library is built on them: Equatable, Comparable, Hashable, Codable are all protocols your types can adopt to get equality, sorting, use as dictionary keys, and JSON encoding. This lesson gives you the foundation to recognize them when you meet them.

Lesson completed