Create Generic Protocols With Associated Types in Swift

How to make protocols generic and the advantages of doing so

Navdeep Singh
Sep 29 · 4 min read
Daria Nepriakhina- Unsplash

While discussing generics in Swift, we learned how to make structs, enums, and classes generic.

We discovered how to pass in abstracted type information at the compile time, leaving it up to the compiler to carry that information from compile time to run time. We used protocols to declare the capability of those types.

But what about protocols? How do we make protocols generic and what are the advantages of doing so?

In this article, we will discuss generic protocols or associated types.

Defining a Generic Protocol

Protocols might come across to you as something that is already generic as any type can conform to a protocol, but what about the internals of the protocol?

Can we come up with a protocol where the internals of the protocol are generic?

The short answer to this question is that it is possible, but implementation is a bit different from what we discussed for other generic types. The first step is to define an interface using a protocol, as shown in the following code:

By definition, a Stack is just an array with limited functionality. In general, a Stack can perform the following functions to the elements it holds:

  • Push an element to the top of the Stack.
  • Pop to remove the top element.
  • Peek at the top element without removing it from the Stack.

Stack is usually used when we want to maintain a LIFO (Last In First Out) order, i.e. we get the last element pushed to the Stack when popping from the Stack.

Now that we understand the functions, let’s define the interface in code:

As Swift is more inclined towards value types, assuming we create our concrete Stack types as structs using arrays, we need to mark the methods mutating in the protocol, as you can see in the code above.

You might have noticed the use of a special argument Element in our protocol. That is because we want any concrete type implementation of this protocol to be able to conform to this protocol and work, despite it containing String, Int, Float, etc.

The final goal is to make sure that each concrete implementation of Stack has one type only.

You might have also noticed the keyword associatedtype while declaring the Element type in our protocol.

Associated types work similar to type parameters and give a placeholder name which is used as part of the protocol.

The actual type is not required until we conform to the protocol to create a concrete implementation.

Protocols can become generic with the use of a special type called associated type.

Associated types can be declared inside the protocols with any constraints with the keyword associatedtype and then use typealias in the generic type to substitute this associatedtype, or we can let the compiler infer the type.

Implementing the Generic Protocol

In the previous section, we discussed how to define a generic protocol using associatedtype. In this section, we will conform to the protocol and create a concrete type.

There are two ways of doing this. The first way is to be explicit about the Element type. Let’s start by creating a concrete type StringStack, as follows:

In the code above, we satisfy the associatedtype requirement by explicitly defining Element to be a concrete type (String in this case), using the typealias keyword.

This tells the compiler that all the methods defined inside the generic protocol will now use String instead of the generic Element type.

Further implementation of the StringStack can now be as follows:

The second way is to let the compiler infer the type for the associatedtype requirement.

As we have specified the type parameter for both functions and the computed property explicitly in the above code, this should be enough for the compiler to infer the type and, hence, we no longer need the typealias keyword.

As a result, even if we remove the typealias declaration, everything should work as expected and the code will look as follows:

This is how we give generic requirements to our protocols. It’s pretty simple but it can be used in many use cases.

As we now know about generic protocols and how to use it, we can now extend our knowledge into more contrived concepts, such as type constraints with generic protocols. We will cover all of that and more in upcoming articles.

Thanks for reading.

Better Programming

Advice for programmers.

Navdeep Singh

Written by

Author of Reactive programming with Swift, Senior Software Engineer — Exploring possibilities with new Tech.

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade