Home What are Associated Types in Swift?
Post
Cancel

What are Associated Types in Swift?

TLDR

Allows us to define placeholder types inside of our protocols, these placeholder’s actual types are then determined by the classes or structs that conforms to the protocol.

Associated types in Swift are a feature that helps to create flexible and reusable protocols. If you don’t know what protocols are, they are like a blueprint or a set of rules that an object that conforms to it can follow. They define what properties (data) and methods (functions) a type should have.

Associated types are useful in situations where a protocol needs to declare methods, properties, or other associated types that rely on some unknown or generic type. By using associated types, you can defer the specification of the actual type to the conforming classes or structs, making the protocol more versatile.

To fully grasp their power, let us take a look at some practical example:

Let’s say we want to create a protocol for a container, like an array or a dictionary. You want this protocol to be flexible enough to work with containers that store different types of elements. Associated types help you achieve this.

1
2
3
4
5
6
protocol Container {
    associatedtype Element
    var count: Int { get }
    func add(element: Element)
    func get(index: Int) -> Element
}

In our example above, Element is a placeholder within the Container protocol. It doesn’t specify the actual type; it just says there will be a type called Element.

Now, let’s create two conforming types:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
struct IntContainer: Container {
    typealias Element = Int // Specify that the associated type Element is Int
    var elements = [Int]()

    var count: Int {
        return elements.count
    }

    func add(element: Int) {
        elements.append(element)
    }

    func get(index: Int) -> Int {
        return elements[index]
    }
}

struct StringContainer: Container {
    typealias Element = String // Specify that the associated type Element is String
    var elements = [String]()

    var count: Int {
        return elements.count
    }

    func add(element: String) {
        elements.append(element)
    }

    func get(index: Int) -> String {
        return elements[index]
    }
}

As you can see by us using associated types, we have now created containers that work with different types of elements without having to rewrite the entire protocol for each specific type.

1
2
3
4
5
6
7
8
9
10
11
var intContainer = IntContainer()
intContainer.add(element: 42)
intContainer.add(element: 87)

var stringContainer = StringContainer()
stringContainer.add(element: "Hello")
stringContainer.add(element: "Swift")

print(intContainer.get(index: 0)) // Output: 42
print(stringContainer.get(index: 1)) // Output: "Swift"

Associated types solved the problem of having to specify a concrete type for the elements directly inside the container protocol. Instead, the conforming types (IntContainer and StringContainer) get to determine the actual type of the elements that they want.

Associated types make your protocol code more generic, which reduces code duplication while keeping type safety.

This post is licensed under CC BY 4.0 by the author.