Swift is one of the topmost type-safe languages nowadays. 🎯🎯🎯
Ohhh wait!! What does it mean if a language is type-safe? 🧐
A type-safe language always ensures that an operation works with the right kind of data available at that point.✓
If a language has the ability to declare different data types (e.g., Int, Float, String, Array, Dictionary) and it has also the ability to ensure that a variable that is declared with a particular data type will never hold a different kind of data, then it is called a type-safe language.
In type-safe languages, type checking is always done. It may happen in compile time or run time depending on the language.✅
Now, what are Generics in Swift?🤫
Generics are type safe, and help us write flexible, reusable functions and types. Using Generics, we can write code that works for all data types. Since Swift is a type-safe language, without breaking this we are able to write generic codes that can avoid code duplication.
Let’s take a simple example: an Array is an ordered collection which can hold the same type of data. That’s why in the definition of an Array, we can see that it takes a generic type of Element. Hence an Array becomes a generic type of Collection.
Ok. Cool. Then what is the Any type in Swift?🤫🤫🤫
Swift also supports the Any type. As the name indicates, it can represent an instance of any type like a struct, class, enum and function type.
So are the Objective C id and Swift’s Any the same?🧐
In Swift 3, the Objective C id type maps to Swift’s Any type. This improves the compatibility of Swift and Objective C.
But how and why?🧐
In Swift 2, the Objective C id was mapped to Swift’s Any object. This worked well for most of the cases, but sometimes it resulted in unexpected behavior. One of the key concepts in Swift is Value Types, and this mapping was not doing the proper justice to this concept.
Swift is just a new language for iOS development, and Objective C has been around for years. So of course most of the projects were developed in Objective C only. Now in order to convert an Objective project to a Swift project, the requirement came that it should be possible to bridge any Swift type to any Objective C object.
But this was not a problem for Swift classes and Swift value types like Int, String, Float because they already have their Objective C counterparts. The problem arose for the Swift value types that did not have any Objective C counterparts.
So to fix this, the Objective C id type mapped onto the Swift Any type.✅✅✅
Enough Definitions 😐. Now let’s come to the main topic. By the above points, it looks like Generics and the Any type are the same. But are they really??😇
On a high level, Any may look similar to Generics. But let’s try to find some differences-🔍🔍🔍
We all know what a Stack is in Data Structures, right? A stack is a basic linear data structure where insertion and deletion of items takes place at one end only.
Now we will implement the Stack structure in Swift. First, we will implement using Generics then with the Any type.
Stack Implementation using Generics:
The above Stack implementation is using Generics. The struct takes a generic type of Element item and implements a stack using that item. Now let’s do some operation with Generic Stack:
It declares a Generic Stack which can hold an Integer type of element. We are pushing the integer element to the stack. Up to this point, everything works great.
But what if I want to push a float element onto that above the genericStack?
❌❌ Oops! Compilation Error! ❌❌
Stack Implementation using the Any type:
In this Stack Implementation, the items array can hold Any type of element. We are not specifying about what will be the exact data type of the items array element in the definition. Now let’s do the same basic operations on this stack:
No issues, right? Everything is working fine here also. Initially, we declared a stack and pushed two integer elements into it. When we call the show() method, it prints the exact array [3, 4].
Now let’s push a float value into it.☄️
✅✅ No Error! Everything works fine! ✅✅
So what is happening behind the scenes? Why we are not getting any error?🧐🧐🧐
Generics basically tells the compiler that:
I have declared a generic type and I am going to give you an exact type later. I want you to apply that type everywhere I specify.
The Any type basically tells the compiler:
Don’t worry about this variable, no need to apply any type here let me do whatever I want to do.
Generics can be used to define flexible functions, but the types of arguments are still checked by the compiler. Any type can be used to dodge Swift’s type system.💯
In the generic stack declaration, we are telling the compiler that the stack should take the integer type only. Then when we are trying to insert a float type of element into it, that means we are breaking that promise. Hence it is throwing a compile time error. It always expects that the element should be an integer type.
But for the Any Stack, we are not getting any compile time or runtime error. Even if we call the show() method, it prints the stack as [3, 4, 5.0] which means the stack holds integer and float type of values. So in any stack, there is no type restriction, we can push any type of value into it (but there are possibilities of runtime exceptions).
So if we use Generics then we can write flexible functions, structures, classes, and protocols without compromising Swift’s type safety. But if we use the Any type, then we are kind of our own boss, we can do almost anything we want.
🙏🙏🙏 Cheers!!! Thank you for reading!! 🙏🙏🙏