Protocol composition allows types to conform to more than one protocol. This is one of the many advantages that protocol-oriented design has over object-oriented design. With object-oriented design, a class can have only one superclass. This can lead to very large, monolithic superclasses, as we saw in the Object-oriented design section of this chapter. With protocol-oriented design, we are encouraged to create multiple smaller protocols with very specific requirements. Let's look at how protocol composition works.
Let's add another protocol, named Occupation, to our example from the Protocol inheritance section:
protocol Occupation {
var occupationName: String { get set }
var yearlySalary:Double { get set }
var experienceYears: Double { get set } }
Next let's create a new type named Programmer that will conform to both the Person and Occupation protocols:
struct Programmer: Person, Occupation { var firstName: String var lastName: String var age: Double var hairColor: String var height: Double var occupationName: String var yearlySalary: Double var experienceYears: Double }
In this example, the Programmer structure conforms to all the requirements from both the Person and Occupation protocols. Keep in mind that the Person protocol is a composite of the requirements from the Name, Age, Hair, and Person protocols; therefore, the Programmer type will need to conform to all those protocols plus the Occupation protocol.
Once again, I want to warn you not to make your protocols too granular. Protocol inheritance and composition are really powerful features, but can also cause problems if used wrongly.
Protocol composition and inheritance may not seem that powerful on their own; however, when we combine them with protocol extensions, we have a very powerful programming paradigm. Let's look at how powerful this paradigm is.