Intro to Generics in Swift

Let’s talk about generics

Often at times when we are coding, we find ourselves duplicating codes to fulfill a function that does exactly the same thing, since our function can only satisfies one type. Let’s see some code as an example:

let names: [String] = ["Mike", "Tom", "Joe", "Mary"]
let nameArray: [String] = []
let ints: [Int] = [1, 2, 3, 4]
let intsArray: [Int] = []
let doubles: [Double] = [10.5, 11.5, 12.5 , 13.5]
let doublesArray: [Int] = []

Here we have three arrays which has names, ints, and doubles. What if we had to append all those arrays into their respective new array, how would we approach this?

func appendNameArray(name: [String]) {
 for name in names {
nameArray.append(name)
}
}
func appendIntsArray(name: [Int]) {
for int in ints {
intsArray.append(int)
}
}
func appendDoubleArray(name: [Double]) {
for double in doubles {
doubleArray.append(double)
}
}

A simple solution would be to create three separate functions that will each take a different type and append into each array. This approach will get the job done, but the only problem is that it is repetitive. We do not need to waste our time to code three functions that does exactly the same thing. If we know ahead of time that we need to create a function that will work for all types, then I have a solution for you, and that is using generics .

Introducing Generics

Generics as the name states implies that it can take in any type and perform a function. Let’s look at some code to give you a general idea

func usingGenerics<theGeneric>(value: theGeneric) {
}

To create a generic type, we need to put our generic type inside of < > after the function. If we need to set our generic as our parameter, we can also do that just but stating that generic type in our parameter. theGeneric is just a arbitrary name that I’ve decided to make up. Generic’s name can be anything you want. The most popular naming convention would be T or U , so those of you who have been studying Swift, and have come across those two letters, it was mostly likely referring to generics.

Using Generics

Let’s take a look back at our original problem above. How can we find a solution to append anything we want to an array?

func anyArray<T>(array: [T], newArray: [T]) -> [T]{
 var copyNewArray = newArray
 for eachElement in array {
 copyNewArray.append(eachElement)
 }
return copyNewArray
}

Viola! With one function, we can now use any type of array and append it into a new array. First we declared that our function will take in an generic element of type T , and all of our parameters is an array of type T . Finally we return an array of type T . As you can see, it is more convenient to create one function to save us some time. This is the power of generics!

Type Contraints

Using generics to accept any type has its pros and cons. Generic’s ability to accept any type is also it’s greatest flaw. In order to make our code safer, it is important to add some limitations. Type constraints has the ability to limit generics to only accept certain classes. Let’s take a look:

class genericClass {}
func makeBurger<T: genericClass> (burger: T) {}

Here we have created a class called genericClass and a function called makeBurger . To make our function to accept only objects from our genericClass , all we have to do is state it after our generic type. Now we can only pass in objects that are of type genericClass in our makeBurger function. If we ever subclassed genericClass , our subclasses will also be able to access this generic function.


That’s all! Thanks for tuning in! 😎

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.