Swift Generics and Associated Types

Prajakta Aher
Globant
Published in
4 min readDec 6, 2020

Introduction

Generics are one of the great features in Swift which allows implementing reusable and abstract code supporting multiple types. This avoids code duplication which makes the code more maintainable. The collections like arrays, dictionaries, and other functionalities in the Swift standard libraries are implemented using generics.

Generics syntax and examples

Following is the implementation to reverse the array of int’s:

Reverse Int array

To implement similar for array of string’s, the function definition would be as follows:

Reverse String array

Similar array method can be implemented to reverse the array irrespective of the fact that elements are of type Int, String or any class or struct using generics. Specify meaningful names to the placeholders instead of random names like ’T’. So we write a generic version of the function to reverse the array. The actual type to use in place of Element is determined each time the generic function is called:

Generic reverse function

For e.g. if we have to return reverse of array excluding some values of same type we can add type constraint, otherwise the compiler will return error:

Error when type constraint not added

Now we will implement a method which returns reverse of array excluding some values in array i.e. not equal to some value.
Swift already provides the Equatable protocol for this. Types that conform to the Equatable protocol can be compared for equality using == or inequality using the “!=“ operator.
So we know that the Type has to conform to Equatable, let’s look at the syntax to specify this:

Equatable is a protocol, but it is possible to specify class and struct types also in constraints.

Generic types

Swift allows to define Generic types like custom classes, struct’s and enum’s. A new instance of ListNode can be created by writing the type to be stored as value within angle brackets. When adding extensions it not required to specify the placeholder type “Element”.

Creating generic types and extensions

Generic where clauses

Generic where clause enable to add a new requirement to the extension. If we have to check if the list node is present in linked list, we will have to check for equality of 2 list node objects. We can specify that using the generic where clause.

Generics where clauses to add additional requirements

Using where clause in the extension , adds method printDescription() only when the NodeValue is CustomStringConvertible.

Associated Types

Since Protocol oriented programming is introduced, we generally start implementation by adding protocols first. Generics can be used in protocols via associatedtype.

Instead of generic types we can specify Any/AnyObject, but that will affect performance since the type of object will be determined at runtime. We will need to add code to type cast from Any/AnyObject to the required concrete type since any object of any type can be passed as parameter.

An associatedtype provides a placeholder name to a type that is used as part of the protocol. The actual type for that associated type isn’t specified until the protocol is adopted.

Following code example contains associated type with generic where clause and generic subscript example. Lets discuss each feature. There is description for each of the mentioned functionalities after the code snippet:

Associated types in Swift

The definition of typealias Element = Int turns the abstract type of Element into a concrete type of Int for this implementation.

Even if we don’t mention the typealias, everything still works due to Swift’s type inference, since the protocol methods are defined with parameter type as Int.

We can still create a Generic linked list type struct and confirm to ”LinkedList” protocol by adding typealias as:
typealias Node = ListNode<NodeType>

We can also specify the type constraint and where clause for the associated types in the protocol to require that the confirming types satisfy those constraints. In this example the generic where clause on the Iterator requires that the iterator must traverse the elements of the type as the Node in the linked list.

We can also add generic subscripts, by writing the placeholder type name in “<>” after subscript. The syntax for the generic subscript is included in the linked list example, which returns the list node at particular index.

The Swift standard library makes extensive use of the Generics and Associated types. I have included the documentation link for protocols in Swift.

Thanks for reading!

--

--