(This is a loose transcription of a talk I gave at the Dutch CocoaHeads meetup in Rotterdam.)
If you paid attention to this year’s WWDC, you’ve probably seen the session on Protocol-Oriented Programming — or at least heard about it.
[Lots of nodding heads in the audience.]
It’s an interesting session and definitely worth checking out. You may also have seen the following in the Xcode 7 release notes:
Protocols can have default implementations for requirements specified in a protocol extension, allowing “mixin” or “trait” like patterns.
In this post I want to talk about these things: protocol-oriented programming, the new protocol extensions, and the mixins and traits that are alluded to here.
If you have experience with other languages such as Ruby or Python — or even PHP! — you may have seen mixins and traits before, but we haven’t had this on iOS or OS X yet. It allows for a slightly different way of programming that has benefits over traditional object-oriented programming.
A quick recap of protocols
First, let’s talk a bit about protocols. I’m going to assume everyone reading this has seen protocols before, although in some languages they’re called interfaces. “Protocols” is the term we use in Objective-C and Swift.
Here’s an example:
A protocol defines an interface. In this case the protocol
Hello has one method
sayHello() that is supposed to return a string.
By itself a protocol isn’t very useful, so you’d create a class or struct that conforms to this protocol, and that implements the methods from the protocol:
And now you can instantiate that class and call the method:
But the cool thing is that this also works if you just have a reference to the protocol part of the object:
h is an instance of
MyClass behind the scenes, but to the compiler — and the programmer — it’s just a
Hello object and therefore, it can only do the things specified in the protocol.
That’s the power of protocols: they let you hide the actual type of your object. The code only cares that this object does what the protocol demands of it, but it does not need to know anything else about the object’s internal structure.
This allows you to program against the interface, not the implementation, and that’s considered to be a good thing.
So even though
h refers to an object that has a
name property, you can’t write
h.name. This property isn’t part of the
Hello protocol and therefore the compiler doesn’t see it.
This is all pretty straightforward and it’s how protocols have always worked on iOS. We use them mostly for the delegate pattern.
New stuff: protocol extensions
A protocol extension is simply this:
The protocol is still the same as before but now there is an extension that gives the
sayHello() method a default implementation.
We’ve had extensions for a while — called “categories” in Objective-C — but these could only be used on classes. As of Swift 2.0 you can also create extensions on protocols.
Now your class simply looks like this:
All you have to do to add that
sayHello() method to your class is conform to the
Hello protocol. You no longer have to implement that method yourself.
Hello a mixin or a trait because it’s a piece of functionality that you add — or mix — into another class.
By the way, you could still implement that method if you wanted to:
This uses the version from
MyClass instead of the default implementation from
You may be wondering, how is this different from inheritance? The big difference is that
MyClass is not a subclass of
sayHello(), you can’t call
MyClass doesn’t have a superclass at all, but we could give it one:
MyClass now consists of the code and properties from
BaseClass, plus the methods from the
Hello protocol. But while you can only have one base class, you can add as many other protocols as you want:
Inheritance is often used as a mechanism for code reuse, but protocol extensions let you reuse code without forcing you into a superclass-subclass relationship.
If you’ve worked with multiple inheritance in C++ you know this can get tricky quite fast. Protocol extensions are a way to do the same thing but simpler and it avoids most of the problems of multiple inheritance.
Composition over inheritance
So why would you want to do this? You may be familiar with the saying, “prefer composition over inheritance”. What this means is that inheritance kinda sucks.
Inheritance was supposed to be one of the big benefits of OOP but in practice it doesn’t work out so well. With inheritance, all the types in your app form this neat hierarchy, but it turns out hierarchies are a pretty limited structure for modeling real-world problems.
Hierarchies aren’t always bad. Here’s an example where inheritance works pretty well:
This is of course the class tree for UIKit. There is a clear hierarchical structure here: a
UIButton is a
UIControl is a
UIView is an
NSResponder. It just makes sense to use inheritance for this.
Here’s another example, from a RayWenderlich.com game tutorial:
This is a castle-defense type game. The players are represented by
Castle objects, one for the human player and one for the computer player. You launch monsters to attack the other player’s castle.
All the objects in the game are based on the
GameObject class, which is an
SKSpriteNode from Sprite Kit.
This class design looks reasonable enough, but there’s a problem. The Zap monster can shoot laser beams at enemy monsters when they come into range. All the logic and data for this shooting algorithm sit inside the
But now we also want the castles to be able to shoot lasers at enemy monsters when they come too close. That’s exactly the same logic, so how do we deal with this in our class hierarchy?
Easy solution: copy-paste the code from
ZapMonster into the
Castle class. But then we have duplicate code and that’s just asking for trouble.
A seemingly better solution is to simply move the shooting code into a common base class,
GameObject. Makes sense, right?
Well, if you’re not careful you end up with a base class that does all the work. This is a typical issue with inheritance hierarchies: a huge base class and many tiny subclasses. (The base class also exposes these methods and their data to the subclasses that don’t need it.)
I’m not really happy with any of these solutions. The best solution I can think of is to put the shooting logic into a class of its own,
ShootingHelper, and give an instance of that to both
Much better, but you still have to manage that helper object — allocate it, clean up after it, and so on — and you may end up with many different types of helper objects for all the different behaviors your game objects need, so it’s not ideal either.
Traits or mixins can help with this. We can flatten the inheritance hierarchy to the following:
Instead of a deep and wide inheritance tree we now just have
GameObject for the base class (it no longer extends from
SKSpriteNode) and directly below that are the classes for the specific objects that make up this game.
In addition, we have a number of traits that describe the different behaviors of these objects.
GunTrait for shooting, a
RenderTrait for drawing the object to the screen (using a sprite node), a
HealthTrait for keeping track of the object’s hit points and drawing a little health bar, and so on.
These traits are all defined as protocols, not classes. And they have extensions that already implement their methods, so the game objects don’t need to implement anything themselves. Just pull in the traits you want and you’re done.
The code for the AI Player simply looks like this:
A monster would look like this:
For each specific object you just pull in the traits you want it to have. Anything that needs to be able to shoot, you make it conform to the
GunTrait protocol and it immediately gets those methods and properties.
In games this is often called a component-based architecture. In fact, the new GameplayKit has an API for this but I wanted to show how you could do it using protocol extensions.
That’s really the idea behind protocol-oriented programming. You use it to simplify inheritance. The inheritance tree is now a lot flatter and if you wanted to you could probably get rid of it completely.
Besides, structs in Swift can’t use inheritance anyway, so if you want to compose a struct from different traits then you have no choice but to use protocols.
Traits vs. Mixins
I’ve been using the terms “trait” and “mixin” for a while now. So what’s the difference between a trait and a mixin? It’s a bit academic and not everyone agrees on these definitions, but it goes something like this:
First off we have the interface. This is a protocol that just has method signatures but no actual code. This is what Objective-C and Swift 1.2 have.
A trait also has the actual method bodies. In other words, a trait adds code to an interface. This is the new thing that Swift 2.0 lets us do today with protocol extensions.
A mixin is like a trait but it also has state. We can’t really do this yet with Swift 2.0 as you’re not allowed to add stored properties to protocols.
Note: You can add a property declaration to a protocol, but then every class or struct that conforms to this protocol still needs to provide its own storage for those properties. So you can sort of do “real” mixins, but it requires some extra work on your part.
Personally, I tend to mix up these names. Sometimes trait sounds better than mixin, but whatever… they pretty much mean the same thing anyway.
Just to avoid any confusion, I want to stress that mixin and trait are the names of the programming patterns. A protocol extension is how you implement those patterns in Swift. But you also do other things with protocol extensions that wouldn’t really be considered mixins or traits.
Example: Login screen
Let’s do a more practical example. Let’s say you have a login screen that needs to validate the username and password to make sure they are well-formed — not too short, not too long, no invalid characters — before you actually send a web service request. This is a fairly common thing to do in iOS apps.
This is one way to implement it:
You could stuff the logic for this into the view controller, but if you do that with everything then before you know it your view controller is 1000 lines long and we all know that Massive View Controller is a bad thing.
One way to do improve on this is to make a separate
UsernameValidator object and put the
isUsernameValid() method into that object. Likewise for the password. That would look something like this:
This is a nice and clean solution. All the validation logic has been hidden away into its own objects, and you can easily reuse these validator objects in other view controllers or even other projects.
However, a cool an alternative is to put the validation method into a mixin:
The validation logic doesn’t sit in a class but in a protocol extension. The protocol declares the
isUsernameValid() method and the extension implements it.
To add this logic into the view controller, all you have to do is this:
By making the view controller conform to the protocols for the
ValidatesPassword mixins, it automatically pulls the
isPasswordValid() methods into the code.
And you can simply call those methods as if they were the view controller’s own:
This is a nice trick to keep your view controllers clean without having to use extra helper objects. I think this is pretty cool. And you can also easily reuse these mixins in other view controllers and in other projects.
Example: Ruby Enumerable
I want to show you one more example. This uses an idea that’s popular in Ruby, the
Enumerable mixin. Ruby has had mixins for long time and they are used to great effect.
It works like this: If you add an
each() method to a class and import the
Enumerable mixin, your class immediately gets a ton of useful methods for enumerating it such as
drop_if(), and so on.
We can do something similar in Swift using protocol extensions.
This is a generic protocol, that’s what the
typealias is for. The important bit is the
each() function. This is something you as the user of this protocol have to provide. It will loop through all the items in your collection, whatever that may be, and passes each item to the closure given by
And then there’s the extension:
This has a whole bunch of functions that are all implemented on top of
dropIf() will return an array with all the elements from your collection, except those that match a given predicate. It’s a way to filter out certain items from the collection. The other methods inside the extension do similar things, all using
each() to step through your collection.
Note that, unlike before, the methods inside the extension aren’t listed in the protocol itself. That keeps the protocol clean and simple.
Let’s say you have some type that you want to make
Enumerable. This type doesn’t have to be an array or dictionary or what we typically think of as a collection — you can treat almost any type as a collection that can be enumerated over.
We have the following type:
(This is based on an example from a Ruby tutorial. Check it out if you want to see how it’s done in that language.)
We can make this struct enumerable as follows:
Just add the
Enumerable protocol and implement the
each() method. In this case, enumerating a
Family object means that we first print out the name of the father, then the name of the mother, and finally the name of the child.
You can use it as follows:
This returns a new array without anyone called Bob.
Thanks to the protocol extension, we get this
dropIf() method for free wherever we conform to
Enumerable. Pretty cool stuff.
Of course, Swift has its own way to do enumeration, with generators. So we can make this a bit more Swift-like.
Instead of using our own
Enumerable protocol, we can create the extension on
GeneratorType. This is one of the built-in protocols from the Swift standard library.
It’s pretty much the same as before, except now we’re using the Swift generator API, which involves calling
next() to iterate through the collection until you get
And now we can call
dropIf() on any generator! Here’s the family example again:
Family now conforms to
SequenceType (another protocol from the Swift standard library) and returns a generator object for iterating through the collection.
Generators are used by Swift with the
for in statement. You can use it like this to step through all the members of the family:
And we can now use
dropIf() like this:
So again, just by making a protocol extension we can inject a whole bunch of functionality into our code without too much effort. You don’t have to copy-paste this
dropIf() method into each of your generators, it’s simply just there.
I said this works on all generators, so this also works:
It doesn’t matter that this is a completely different type of data structure. Because we added
dropIf() to an extension on
GeneratorType, it magically works anywhere. How is that for code reuse!
One final thing I should mention is that you can restrict a protocol extension to particular types, which is handy if you’re dealing with generics.
So let’s say we want to limit the
dropIf() function to just generators for strings, then we could write the following:
The only thing that’s different here is the
dropIf() will still work with the
Family struct because its generator returns strings, but it will no longer work on the array of integers from the previous example. Generators that don’t return strings simply won’t have that
The takeaway is that, if you’re considering making an inheritance hierarchy with lots of superclasses and subclasses, try using protocols instead.
With inheritance the only structure you can make is a hierarchy. But by placing your reusable code in protocol extensions, you’re no longer limited to just hierarchies — you’ve got more freedom in how you stick your building blocks together to build bigger components.