Skip to main content

Day 11

About 5 minSwiftcrashcoursepaul-hudsonswifthacking-with-swiftxcodeappstore

Day 11 ꎀ렚


Protocols and extensions

Today you’re going to learn some truly Swifty functionality: protocols and protocol-oriented programming (POP).

POP does away with large, complex inheritance hierarchies, and replaces them with much smaller, simpler protocols that can be combined together. This really is the fulfillment of something Tony Hoare said many years ago: “inside every large program, there is a small program trying to get out.”

Today you have six one-minute videos to watch, and you’ll meet protocols, extensions, and the combination of those two: protocol extensions. Once you’ve watched each video and any optional extra reading you wanted, there’s a short test to help make sure you’ve understood what was taught.

1. Protocols

1. Protocols
100 Days of Swift - Day 11 - 1. Protocols

1. Protocols

Protocols are a way of describing what properties and methods something must have. You then tell Swift which types use that protocol – a process known as adopting or conforming to a protocol.

For example, we can write a function that accepts something with an id property, but we don’t care precisely what type of data is used. We’ll start by creating an Identifiable protocol, which will require all conforming types to have an id string that can be read (“get”) or written (“set”):

protocol Identifiable {
    var id: String { get set }
}

We can’t create instances of that protocol - it’s a description of what we want, rather than something we can create and use directly. But we can create a struct that conforms to it:

struct User: Identifiable {
    var id: String
}

Finally, we’ll write a displayID() function that accepts any Identifiable object:

func displayID(thing: Identifiable) {
    print("My ID is \(thing.id)")
}

2. Protocol inheritance

2. Protocol inheritance
100 Days of Swift - Day 11 - 2. Protocol inheritance

2. Protocol inheritance

One protocol can inherit from another in a process known as protocol inheritance. Unlike with classes, you can inherit from multiple protocols at the same time before you add your own customizations on top.

We’re going to define three protocols: Payable requires conforming types to implement a calculateWages() method, NeedsTraining requires conforming types to implement a study() method, and HasVacation requires conforming types to implement a takeVacation() method:

protocol Payable {
    func calculateWages() -> Int
}

protocol NeedsTraining {
    func study()
}

protocol HasVacation {
    func takeVacation(days: Int)
}

We can now create a single Employee protocol that brings them together in one protocol. We don’t need to add anything on top, so we’ll just write open and close braces:

protocol Employee: Payable, NeedsTraining, HasVacation { }

Now we can make new types conform to that single protocol rather than each of the three individual ones.

3. Extensions

3. Extensions
100 Days of Swift - Day 11 - 3. Extensions

3. Extensions

Extensions allow you to add methods to existing types, to make them do things they weren’t originally designed to do.

For example, we could add an extension to the Int type so that it has a squared() method that returns the current number multiplied by itself:

extension Int {
    func squared() -> Int {
        return self * self
    }
}

To try that out, just create an integer and you’ll see it now has a squared() method:

let number = 8
number.squared()

Swift doesn’t let you add stored properties in extensions, so you must use computed properties instead. For example, we could add a new isEven computed property to integers that returns true if it holds an even number:

extension Int {
    var isEven: Bool {
        return self % 2 == 0
    }
}

4. Protocol extensions

4. Protocol extensions
100 Days of Swift - Day 11 - 4. Protocol extensions

4. Protocol extensions

Protocols let you describe what methods something should have, but don’t provide the code inside. Extensions let you provide the code inside your methods, but only affect one data type – you can’t add the method to lots of types at the same time.

Protocol extensions solve both those problems: they are like regular extensions, except rather than extending a specific type like Int you extend a whole protocol so that all conforming types get your changes.

For example, here is an array and a set containing some names:

let pythons = ["Eric", "Graham", "John", "Michael", "Terry", "Terry"]
let beatles = Set(["John", "Paul", "George", "Ringo"])

Swift’s arrays and sets both conform to a protocol called Collection, so we can write an extension to that protocol to add a summarize() method to print the collection neatly

extension Collection {
    func summarize() {
        print("There are \(count) of us:")

        for name in self {
            print(name)
        }
    }
}

Both Array and Set will now have that method, so we can try it out:

pythons.summarize()
beatles.summarize()

5. Protocol-oriented programming

5. Protocol-oriented programming
100 Days of Swift - Day 11 - 5. Protocol-oriented programming

5. Protocol-oriented programming

Protocol extensions can provide default implementations for our own protocol methods. This makes it easy for types to conform to a protocol, and allows a technique called “protocol-oriented programming” – crafting your code around protocols and protocol extensions.

First, here’s a protocol called Identifiable that requires any conforming type to have an id property and an identify() method:

protocol Identifiable {
    var id: String { get set }
    func identify()
}

We could make every conforming type write their own identify() method, but protocol extensions allow us to provide a default:

extension Identifiable {
    func identify() {
        print("My ID is \(id).")
    }
}

Now when we create a type that conforms to Identifiable it gets identify() automatically:

struct User: Identifiable {
    var id: String
}

let twostraws = User(id: "twostraws")
twostraws.identify()

6. Protocols and extensions summary

6. Protocols and extensions summary
100 Days of Swift - Day 11 - 6. Protocols and extensions summary

6. Protocols and extensions summary

You’ve made it to the end of the ninth part of this series, so let’s summarize:

  1. Protocols describe what methods and properties a conforming type must have, but don’t provide the implementations of those methods.
  2. You can build protocols on top of other protocols, similar to classes.
  3. Extensions let you add methods and computed properties to specific types such as Int.
  4. Protocol extensions let you add methods and computed properties to protocols.
  5. Protocol-oriented programming is the practice of designing your app architecture as a series of protocols, then using protocol extensions to provide default method implementations.

6. Protocols and extensions summary - Additional

That’s day 11 complete, so hopefully by now you know what to do: go and post about your progress online on Twitter, Facebook, Reddit, or whatever social media you like. You’re powered by POP now!


ìŽì°ŹíŹ (MarkiiimarK)
Never Stop Learning.