Generics in Swift
Generic programming is a way of writing a reusable functions & types in a flexible way
Its a feature of swift, much of swift standard libaray build with generic code.
lets understand it solving the existing problem
The above function swaps the two Int using pass by reference, now if I need to write a function which does swaping of strings, I would be writing one more function like shown below
As you can see the implementation body of both functions are same, the only difference is in the type of parameters.
Now lets see how Generics solves the above duplicity of code
Thats how our generic function to swap two values will look like,
- <T> just after the function name indicating this is a generic function which take parameters of type T
- Function arguments list contains the Type as T instead Int, Double or String, which would be replaced with actual type
The below code shows how the above generic function swapTwoValues
used for swapping Strings, Int values.
So thats quick Intro of Generics, Generic Function.
Topics we would be covering reading further
- Generic Types
- Type Constraint to Generic Functions/Types
- Associated Types
Generic Types
As expected, yea!! you can write generic types in swift, the most common types we use day to day the Array, Dictionary are Generic Types
lets dig into the code without any further theory
The above structure IntStack
which uses an array to push and pop the Int items to stack, the `push() & pop()
` functions are mutating because they are modifying the structure items array.
Now lets see if I need a generic type which can push and pop not only Int item types but also other types.
There is not much difference isn't it?
Struct Name is appended with generics syntax <Element>
where Element is a Type which would be replaced with actual Types (Int, Double, Strings, etc)
Element
used as place holder in three places
- The property
items
which is initialized with array of values of typeElement
- The
push()
function is taking a parameter of typeElement
- Return value of funtion
pop()
is of typeElement
The above code shows how we have used the Generic Stack
pushing and popping items of type String and Int.
Extending Generic Type
The above snippet is an extention of value type Stack
with topItem
as computed property in it, topItem
is of type Element
will return nil if stack is empty else the last item.
Type Constraint to Generic Functions/Types
In swift we can enforce certain type constraint on the types that can be used with generic functions and types
Didn't get ?
May be lets read the below line and try mapping it again.
We can define a generic function or type with a rule saying,
- Type used should always confirm to a particular protocol or protocol composition
- Type used should be inherited from a particular class
For example, In Swift’s Dictionary
dictionary’s keys must always confirm to protocol Hashable
else it cannot be used as key in Dictionary
Lets see a generic function with type constraint
<T:Equatable>
the syntax indicate that the generic function will take types only confirming to protocol Equatable
By default all Data types String, Int, Double, etc are confirming to protocol Hashable
which confirms Equatable
protocol , so the above code works with out any issue.
Lets not wait to see a generic type with type constraint, will create a NavigationControllerStack
for pushing and popping viewcontrollers which is of class UIViewControllers or its subclasses
Thats how the NavigationControllerStack
looks like, the syntax <Element:UIViewController>
after the class name indicates that, this class will take Element
only if they are inherited from UIViewController.
In the above code snippet, we create a ContactsViewController
instance which is inherited from UIViewcontroller and Push to the NavigationControllerStack
, same way PeopleViewController
instance which is inherited from UIViewcontroller is Pushed.
Associated Types in Generics
Here we will see how we can use generics in protocols. Unlike classes, structs, enums, protocols supports generics in different way, the swift terminology calls it as Associated Types
An associated type in protocol says
“I dont know what exact type this is, some concrete class/struct/enum that adopts me will fill in the details.”
The above snippet shows the declaration of Containment
protocol , Containment
declares an `associatedtype` called Item
which protocol doesn't know what exact type it is, the class or struct who implements Containment
will know about it.
The Container
protocol defines two required capabilities that any container must provide:
- It should be able access the top item in the container through function
topItem()
at returns aItem
type - It should be able to access a count of the items in the container through a
count
property that returns anInt
value.
Will use the the above Containment
Protocol in our Stack
value type
The protocol Containment
with associated type Item
which was as place holder filed by our Stack
struct as Element
Means the protocol funtion topItem()
returns the item of type Element
which was Item
in protocols declaration.
Thats about the basics of Generics and related topics, If interested further feel free to check out the TRIE Data stucture Implemented using Generics.