Type Erasure in Swift
If we are working with a protocol having associated type requirements, we might sometimes need the help of type erasure. I will explain the reason with a step by step approach. Let’s first start with a regular protocol with no associated type:
In this example, we have a BusinessRule protocol without any associated type requirements. There are two different implementation for this protocol: BusinessRule1 and BusinessRule2. BusinessManager has a property of type BusinessRule protocol, this makes us flexible so while initating the BusinessManager struct, we can use any concrete type conforming to this protocol as shown in the example.
Up until now we have no problem. But let’s see what happens if we have an associated type requirement in our protocol:
We added an associatedtype name Model to our protocol and modified the function to add a parameter of type Model. Now as seen in above screenshot, we get an error in our BusinessManager struct because our protocol now has an associatedtype requirement. Let’s try to create a concrete type named BusinessModel1 and associate it with our protocol’s associatedtype:
No, it did not work because generic protocols can not infer their types in the declaration. Now it is the time for the type erasure…
Here, we are creating a new concrete type named AnyBusinessRule and it conforms to our protocol named BusinessRule. In initialization, we are expecting another concrete type conforming to BusinessRule and setting references for all the methods of this concrete type; in our case, there is just one function named doBusiness.
So, in the end, here’s how we can use our type erased type:
In BusinessManager struct, rule variable is of type AnyBusinessRule and as seen in lines 41 and 44, in initialization, we can pass any BusinessRule we want.
As a last note, all we wanted was to keep BusinessManager non-generic. If we are okay to make it generic, we do not need any type erasure as shown here:
Only downside of this approach is that, we can not change the type of BusinessRule at run-time as seen in the screenshot.