Polymorphism using Protocols in Swift

Sandeep Bhandari
Mac O’Clock
Published in
4 min readMay 11, 2020

Let’s kickstart it with a simple definition of what is Polymorphism?

confused

As I remember reading it in engineering, It’s the ability to behave differently under different condition. For example, A person might be a son to his parents and an employee in a company at the same time, and hence will behave differently according to the environment he is currently part off.

In a programming world, polymorphism allows us to have different implementations of the action with same name and based on the context, specific implementation of the action will be triggered.

There are two types of polymorphism,

  1. Static Polymorphism: This kind of polymorphism can be achieved by using function overloading. Here functions will have same name but different signatures and based on signature of the call, specific implementation will be triggered. (Static Dispatch)
  2. Dynamic Polymorphism: This kind of polymorphism can be achieved, when parent and child objects have different implementation of the same method (function overriding), and run time decides which implementation to trigger based on the type of the object at hand (Dynamic Dispatch)

How will you achieve polymorphism using protocols in swift then?

thinking

Dynamic polymorphism:

Let’s assume, we would like all our classes to implement a functionality to print their name and their author name as description on console. So lets go ahead and create a Description protocol,

Now each class can confirm to this protocol and provide their own implementation of describe as shown below

Great! Lets assume you pass one of this class instances as an argument to your ViewController, so in your ViewController you declare the variable as

Now when you call describe on this variable, compiler will not know which specific instance will be passed to it, so it can’t decide which specific implementation of describe to trigger at compile time.

Only during run time, swift runtime gets to know the concrete instance on which describe is called and calls the specific implementation accordingly, (Dynamic Dispatch) hence results in Dynamic polymorphism.

Static polymorphism using associatedtype:

Let’s assume, we would like to implement an add function on two basic types namely Int and String. Some of our classes would like to pass two integers to it and expect it to return the sum of them, while some of our classes would like to pass strings and expect the function to concatenate them.

Generic Operations Protocol

In order to introduce Generics into protocol, I am using associatedtype. Associatedtype will help us achieve static polymorphism and not dynamic polymorphism.

Now one common solution here, is to make our classes to confirm to this protocol and have their own custom implementation of add function, isn't it?

Too easy

But wait! wouldn’t it be better, if we can write these implementation only once and share it across multiple classes.

Let’s use protocol default extension to create a different implementation of add function based on the operand type passed.

Now each view controller can confirm to this protocol and declare their type alias, and based on the operand type declared in type alias, specific implementation will be triggered.

Here each class confirming to GenericOperations protocol will have to specify certain typealias hence swift compiler can easily identify which specific implementation of add to trigger at compile time itself (Early/Static Dispatch), so this results in Static polymorphism.

voila!! you have achieved both static and dynamic polymorphism using Protocol in swift.

Issues with this static polymorphism using associatedtype?

You have used associatedtype to introduce generics in your GenericOperations protocol. Let’s assume, you would like to hold a reference to any class that confirms to GenericOperations protocol? How would you declare a variable as?

Isn’t it? This will immediately give you a compilation error.

Protocol ‘GenericOperations’ can only be used as a generic constraint because it has Self or associated type requirements

Thats right, you can’t use GenericOperations as a concrete type! How can you solve it? You can solve it using TypeErasure technique, but thats a topic for another post :)

--

--