Generics are an important part of the Swift programming language. They allow us to create functions that make few assumptions about the underlying data types of its arguments and can be used with multiple data types.
Consider the following function:
func max(x: Double, y: Double) -> Double { return x > y ? x : y }
The above function accepts two Double
type arguments and returns the maximum among the two. What if we wanted to find the max of two Int
type values? We cannot do it using the above function as it accepts only Double
arguments. So, we’d have to write a different function.
func max(x: Int, y: Int) -> Int { return x > y ? x : y }
It would take a long time to write out a function for each type!
Fortunately, using Generics, we can construct a function that accepts both Int
s and Double
s.
func max<T: Comparable>(x: T, y: T) -> T { return x > y ? x : y }
The function name max
is accompanied by <T: Comparable>
. T
denotes the placeholder data type and is enclosed within angular brackets.
: Comparable
shows that T
conforms to the Comparable
protocol but we don’t know T
’s exact type. Conformance to Comparable
is necessary in this case because it guarantees that values x
and y
can be compared with each other. More about Comparable
here.
Both Int
and Double
conform to Comparable
, so this function can be used with both Int
and Double
types. However, both arguments have to be of the same type.
This is how the function can be called with Int
values:
let maxInt = max(x: 10, y: 12)
And this is how it can be called with Double
values:
let maxDouble = max(x: 22.87, y: 66.23)
It is also possible to have generic functions that allow different data types in their arguments.
func buildSingleEntryDictionary<Key, Value>(withKey key: Key, andValue value: Value) -> [Key: Value] { var dict = [Key: Value]() dict[key] = value return dict } let populations = buildSingleEntryDictionary(withKey: "India", andValue: 1.37) let classes = buildSingleEntryDictionary(withKey: "Ms. Frizzle", andValue: ["Arnold", "Carlos", "Dorothy"])
By using generics, you can create functions that work with different types!
Instructions
Modify the tripleValues(in:)
to accept any value that conforms to Numeric
. Structs that conform to the Numeric
protocol can be multiplied. Double
s and Int
s both conform to Numeric
.
Use T
as the placeholder value for the generic type.
Call tripleValues(in:) on
intArrand print the value. Then do the same thing with
doubleArr`. Our tripling function will now work with all kinds of numbers!