Swift generics
Published: 2021-04-25 22:59:30

*Note: This article is part of the course* **Introduction to iOS using UIKit** *I've given many times in the past. The course was originally in Spanish, and I decided to release it in English so more people can read it and hopefully it will help them.*

# The problem

Let's imagine we need to write a `Stack` data structure. We could do something like this:

```swift
struct Stack {
    private var content: [Int] = []

    var topElement: Int? {
        return content.last
    }

    mutating func push(_ element: Int) {
        content.append(element)
    }

    mutating func pop() -> Int? {
        return content.popLast()
    }
}
```

And we can use it like this:

```swift
var stack = Stack()
stack.push(10)
stack.push(20)
print(stack.topElement) // 20
stack.push(15)
let topElement = stack.pop()
print()
```

The problem we'll have with this type is that if we need to define a `StringStack`, then we'd have to repeat the entire code!

```swift
struct StringStack {
    private var content: [String] = []

    var topElement: String? {
        return content.last
    }

    mutating func push(_ element: String) {
        content.append(element)
    }

    mutating func pop() -> String? {
        return content.popLast()
    }
}
```

# The solution

The solution to that problem is **generics**, and it consists on replacing the specific types that will vary from implementation to implementation, by a template or generic type.

```swift
struct Stack<T> {
    private var content: [T] = []

    var topElement: T? {
        return content.last
    }

    mutating func push(_ element: T) {
        content.append(element)
    }

    mutating func pop() -> T? {
        return content.popLast()
    }
}
```

We don't have a `IntStack` and a `StringStack` as separate types anymore. What we have now is a `Stack` of type `T`, and that `T` can be replaced by a concrete type when we need a `Stack`.

```swift
var stack = Stack<Int>()
stack.push(10)
stack.push(20)
print(stack.topElement) // 20
stack.push(15)
let topElement = stack.pop()
print()
```

# Constrained generics

Sometimes we need to force generic types to implement certain requisites. The most common case is that we need the generic type to implement a protocol.

```swift
protocol Noisy {
    func makeNoise() 
}

struct RingBell: Noisy {
    func makeNoise() {
        print("Ring!")
    }
}

struct Dog: Noisy {
    func makeNoise() {
        print("Woof!")
    }
}
```

Let's now imagine we want to create a noisy stack, so we can then have all our noisy objects to make noise at the same time!

```Swift
struct NoisyStack<T: Noisy> {
    private var content: [T] = []

    var topElement: T? {
        return content.last
    }

    mutating func push(_ element: T) {
        content.append(element)
    }

    mutating func pop() -> T? {
        return content.popLast()
    }

    func makeNoise() {
        for item in content {
            item.makeNoise()
        }
    }
}
```

In this case, as the items in the `NoisyStack` are `Noisy`, we know that all the items on can make noise.

# Examples

There are other examples of generic types we have been using so far.

The first one is `Array`. When we write `[Int]`, we're actually creating a `Array<Int>`, but with a simplified syntax.

The second example is probably more interesting. `Int?` is actually `Optional<Int>`, but with some syntax sugar on it, but it's exactly the same as writing something like this:

```swift
enum Optional<Wrapped> {
    case none
    case some(Wrapped)
}
```