Polymorphism with protocols

The word polymorphism comes from the Greek roots polys (meaning many) and morphe (meaning form). In programming languages, polymorphism is a single interface to multiple types (many forms). There are two reasons to learn the meaning of the word polymorphism. The first reason is that using such a fancy word can make you sound very intelligent in a casual conversion. The second reason is that polymorphism provides one of the most useful programming techniques not only in object-oriented programming, but also protocol-oriented programming.

Polymorphism lets us interact with multiple types though a single uniform interface. In the object-oriented programming world, the single uniform interface usually comes from a super class, while in the protocol-oriented programming world that single interface usually comes from a protocol.

In the last section we saw two examples of polymorphism with Swift. The first example was the following code:

var myPerson: PersonProtocol

myPerson = SwiftProgrammer(firstName: "Jon", lastName: "Hoffman", birthDate: bDateProgrammer)

myPerson = FootballPlayer(firstName: "Dan", lastName: "Marino", birthDate: bDatePlayer)

In this example we had a single variable of the PersonProtocol type. Polymorphism allowed us to set the variable to instances of any type that conforms to the PersonProtocol protocol, such as the SwiftProgrammer or FootballPlayer types.

The other example of polymorphism was in the following code:

var programmer = SwiftProgrammer(firstName: "Jon", lastName: "Hoffman", birthDate: bDateProgrammer)

var player = FootballPlayer(firstName: "Dan", lastName: "Marino", birthDate: bDatePlayer)

var people: [PersonProtocol] = []
people.append(programmer)
people.append(player)

In this example we create an array of PersonProtocol types. Polymorphism allowed us to add instances of any types that conform to PersonProtocol to this array.

When we access an instance of a type though a single uniform interface as we just showed, we are unable to access type-specific functionality. As an example, if we had a property in the FootballPlayer type that records the age of player, we would be unable to access that property because it is not defined in the PeopleProtocol protocol.

If we do need to access type-specific functionality, we can use type casting.