Generics in Objective-C
Generics offers flexibility in programming and is a widely adopted pattern in many languages. For iOS developers, we all know Generics in Swift is super powerful. For Objective-C, does it has Generics as well?
The answer is yes. Apple introduces Generics in Objective-C since 2015. The main goal is to enable Swift Generics to convert to Objective-C syntax without extra overhead (as it is called as “lightweight generics”). While at the same time, Objective-C could also enjoy the flexibility that Generics bring about. Let us see how it looks like.
Here is an example of a queue with enqueue and dequeue functions implemented with Generics.
In Queue.h, we use <ObjectType>
as element for the queue, which means the specific type of the element could be provided later in real use cases.
For implementation, here we use id
in .m file for element type instead of <ObjectType>
, otherwise the compiler will throws an error saying “Expected a type”.
And to use the queue with generics is very straightforward:
Another thing worth noting about Generics in Objective-C is casting. Imagine we have two instances, one is the superclass of the other. How can we convert a queue holding superclass objects to a queue with subclass and vise versa?
If we directly cast one from the other as above, compiler will not do the job as we expected; instead it gives us a warning. To successfully cast from queue of subclass instances to the one with superclass ones, __covariant
is the answer. Let us go back to Queue.h and add the keyword to Queue:
Similarly, the keyword__contravariant
enables us to cast Queue<Sup *>
to Queue<Sub *>
. However, it is not permitted to use both __contravariant
and __covariant
at the same for type declaration.
In conclusion, __covariant
is to indicate that subtypes are acceptable, and __contravariant
to indicate that supertypes are acceptable. This can be seen in many cases such as the interface of NSArray.
For more details, you could reference Lightweight Generics topic by Apple.