Swift Generics

Swift Generics allows us to create a single function and class (or any other types) that can be used with different data types.

This helps us to reuse our code.


Swift Generic Function

In Swift, we can create a function that can be used with any type of data. Such a function is known as a Generic Function.

Here's how we can create a generic function in Swift:

// create a generic function
func displayData<T>(data: T){
  ...
}

Here,

  • We have created a generic function named displayData().
  • T used inside the angle bracket <> is called the type parameter.

And based on the type of the value passed to the function, the T is replaced by that data type (Int, String, and so on).

Note: We can provide any name to the type parameter: <S>, <Element>, etc. But generally, we use T.


Example: Swift Generic Function

  // create a generic function
func displayData<T>(data: T) {
  print("Generic Function:")
  print("Data Passed:", data)
}

// generic function working with String
displayData(data: "Swift")

// generic function working with Int
displayData(data: 5)

Output

Generic Function:
Data Passed: Swift
Generic Function:
Data Passed: 5

In the above example, we have created a generic function named displayData() with the type parameter <T>.

Now, when we call the generic function

displayData(data: "Swift")

we have passed a string value, so the placeholder parameter T is automatically replaced by String.

Similarly, when we pass Int to the generic function

displayData(data: 5)

the placeholder is replaced by Int.


Swift Generic Class

Similar to the generic function, we can also create a class that can be used with any type of data. Such a class is known as Generic Class.

Let's see an example,

// create a generic class
class Information<T> {

  // property of T type
  var data: T

  init (data: T) {
    self.data = data
  }

  // method that return T type variable
  func getData() -> T {
    return self.data
  }
}

// initialize generic class with Int data
var intObj = Information<Int>(data: 6)
print("Generic Class returns:", intObj.getData())

// initialize generic class with String data
var strObj = Information<String>(data: "Swift")
print("Generic Class returns:", strObj.getData())

Output

Generic Class returns: 6
Generic Class returns: Swift

In the above example, we have created a generic class named Information. This class can be used to work with any type of data.

class Information<T> {...}

We have created two objects of Information

var intObj = Information<Int>(data: 6)

var strObj = Information<String>(data: "Swift")

Here,

  1. intObj - the type parameter T is replaced by Int. Now, the Information works with integer data.
  2. stringObj - the type parameter T is replaced by String. Now, the Information works with string data.

Type Constraints in Swift Generics

In general, the type parameter can accept any data type (Int, String, Double, ...).

However, if we want to use generics for some specific types (such as accepting data of number types) only, then we can use type constraints.

Here's how we create type constraints:

func addition<T: Numeric>(num1: T, num2: T) {
  ...
}

Here, <T: Numeric> adds constraints to the type parameter. It defines that T needs to conform to the Numeric protocol.

Note: Numeric is the built-in protocol for numeric values like Int and Double.


Example: Type Constraints

//create a generic function with type constraint
func addition<T: Numeric>(num1: T, num2: T) {

  print("Sum:", num1 + num2)
}

// pass Int value
addition(num1: 5, num2: 10)

// pass Double value
addition(num1: 5.5, num2: 10.8)

Output

Sum: 15
Sum: 16.3

In the above example, we have created a generic function named addition(). Notice the expression,

<T: Numeric>

Here, the generic function is created with type constraints. This means addition() can only work with data types that conform to Numeric protocol (Int, Double, and so on).

Note: If we try to pass other types, say String, we'll get an error: argument type 'String' does not conform to the expected type 'Numeric'.


Advantages of Swift Generics

1. Code Reusability

With the help of generics in Swift, we can write code that will work with different types of data. For example,

func genericFunction<T>(data: T) {...}

Here, we have created a generics function. This same function can be used to perform operations on integer data, string data, and so on.

2. Used with Collections

Swift array uses the concept of generics. For example,

// creating a integer type array
var list1: Array<Int> = []

// creating a string type array
var list2: Array<String> = []

Here, list1 array that holds Int values and list2 array that holds String values.

Similar to arrays, dictionaries are also generic in Swift.

Did you find this article helpful?