Advanced Swift Feature: Generics

A portrait painting style image of a pirate holding an iPhone.

by The Captain

on
April 15, 2023

Advanced Swift Feature: Generics

Generics in Swift allow us to write flexible and reusable code that can work with different types. This feature is particularly useful when working with collections because it allows us to write functions and classes that work with a variety of types of data, rather than having to write a separate implementation for each type we want to work with.

Defining a Generic Function

Let's start by looking at how we can define a basic generic function. In this example, we will create a simple function called swapValues that takes two generic arguments and swaps their values:

func swapValues<T>(_ a: inout T, _ b: inout T) {
    let temporaryA = a
    a = b
    b = temporaryA
}

We start by declaring the function in the usual way, with the func keyword, followed by the function name, and then the argument list in parentheses. Here, we have two arguments, both of type inout T, meaning that they are mutable and of a generic type T.

Inside the function, we create a temporary variable to store the value of a, then we assign b to a, and finally we assign the temporary value of a to b.

The beauty of this function is that it can work with any type that is Equatable and can be mutated. We can call this function with integers, strings, and even custom objects, as long as they conform to the constraints we have set on the generic type.

Using a Generic Type

To demonstrate how we can use generics in a class, let's create a simple Stack implementation that can work with any type of data:

class Stack<T> {
    private var elements = [T]()
    
    func push(_ element: T) {
        elements.append(element)
    }
    
    func pop() -> T? {
        return elements.popLast()
    }
}

Here, we have defined a class called Stack that has a generic type T. Inside the class, we have an array of type [T] that will store our elements.

We have also defined two methods, push and pop, which allow us to add and remove elements from the stack. Note that pop returns an optional type T?, because there may not be any elements left in the stack to pop.

Conclusion

Generics are a powerful feature in Swift that allow us to write flexible and reusable code. We can define generic functions and classes that work with a variety of types, and this makes our code more concise and easier to maintain. By understanding how to use generics, we can write more efficient, effective and scalable code.