Protocol Composition In Swift
Are you feeling that your interfaces are too fat and you would like to split them? Protocol composition is the solution to your problems.
If we want to write clean code, we should split our interface in little protocols with cohesive properties and methods. The problem of having several protocols is that we often need to use some of them together. For example, we may want to declare a variable of a type which combines some protocols together. The solution is using protocol composition.
In this article, we’re going to see two approaches to achieve protocol composition in Swift.
Let’s consider the following protocol:
It has a method to return the content of a file and a method to write a
String inside a file.
The problem of this protocol is that it breaks the
Interface Segregation Principle.
FileHandlerType is a fat interface, it contains methods not cohesive. If we want to follow the SOLID principles, we should get rid of
FileHandlerType and split it in two protocols like these:
This refactoring brings us a problem. Before the refactoring, we could declare a variable of type
FileHandlerType and use its methods
After the refactoring, we no longer have
FileHandlerType. We have two protocols. How can we declare a variable of a type which combines
FileHandlerWritable? Protocol composition can save our day.
In the next sections, we’re going to see two approaches to manage protocol composition. A basic one—which is a generic object-oriented programming approach—and a more “Swifty” one.
This approach is very generic. We can use it also in other languages like Java.
We can create an empty protocol
FileHandlerType which extends both
In this way,
FileHandlerType inherits the methods of both
FileHandlerWritable. At this point, we can finally declare a variable of type
We may have the concern that this approach is similar to having only a single protocol
FileHandlerType like this:
The difference is that, with this approach, we don’t break
Interface Segregation Principle. We still have an interface split in two protocols
If you don’t like
Basic Approach, there are good news for you. Swift provides a more “Swifty” way to achieve protocol composition.
If we want to combine two or more protocols together, we can use the operator
&. We can combine
FileHandlerWritable like this:
This approach has just a downside. If we combine several protocols, we start having a messy code:
For this reason, I would suggest you to use a
typealias to clean the declaration of our variables:
You can check a real usage of this approach in the file
StorageContext.swift of the open source library
I usually prefer using the
Swifty Approach. In this way, I can avoid creating a new empty protocol only to combine different protocols together. Then, I always use a
typealias to clean the concatenation of protocols.