It’s by no means been simpler!

Dynamic dispatch is likely one of the most essential mechanisms in Object-Oriented Programming (OOP). It’s the core mechanism that makes run-time polymorphism attainable, enabling builders to put in writing code that decides their execution path throughout run-time moderately than compile-time.
As straightforward because it appears to attain dynamic dispatch in OOP, it’s not the case with regards to Protocol-Oriented Programming (POP). Attempting to perform dynamic dispatch utilizing protocols all the time comes with unpredicted difficulties on account of varied limitations within the Swift compiler.
With the discharge of Swift 5.7, all these have grow to be historical past! Attaining dynamic dispatch within the realm of POP has by no means been simpler. On this article, let’s discover what sort of enhancements we get from Swift 5.7 and what it takes to perform dynamic dispatch utilizing protocol with related varieties.
So with out additional ado, let’s get proper into it!
Notice:
If you happen to’re unfamiliar with the
some
andany
key phrase in Swift, I extremely encourage you to first learn my weblog put up referred to as “Understanding the “some” and “any” keywords in Swift 5.7“.
Earlier than I can begin displaying you the enhancements in Swift 5.7, let’s outline the protocols and structs that we’d like for our pattern code all through this text.
The definitions now we have above are much like what we’re utilizing in my previous article, however with a bit little bit of a twist. Right here in our Automobile
protocol, now we have 2 operate necessities, startEngin()
and fillGasTank(with:)
. For the sake of demonstration, We are going to attempt to obtain dynamic dispatch utilizing these 2 features in each Automobile
and Bus
structs.
Now, let’s say we need to create a startAllEngin()
operate that accepts a heterogeneous array as proven under:
You’ll discover that that is actually unattainable in Swift 5.6 as you’ll be prompted with an error saying: “Protocol ‘Automobile’ can solely be used as a generic constraint as a result of it has Self or related kind necessities”. The Swift compiler is prohibiting us to create a heterogeneous array with Automobile
as its factor kind on account of the truth that Automobile
has an related kind (FuelType
).
Professional Tip:
If you want to study extra concerning the error, and how one can work round it previous to Swift 5.7, take a look at my article printed on Medium: “Swift: Accomplishing Dynamic Dispatch on PATs (Protocol with Associated Types)“
Because of the improve Apple made to the Swift compiler, this limitation now not exists in Swift 5.7. We are able to lastly use a protocol similar to how we use a superclass in OOP. Let me present you the way.
In Swift 5.7, making a heterogeneous array is now not prohibited by the compiler. All we have to do is to make use of the any
key phrase.
Through the use of the any
key phrase, we’re telling the compiler that the array will include existential varieties and that their underlying concrete kind will all the time conform to the Automobile
protocol.
With that, calling startAllEngin(for:)
will give us the dynamic dispatch that we would like.
Now let’s check out one other extra sophisticated instance. Let’s say we need to create a operate named fillAllGasTank(for:)
. This operate will carry out dynamic dispatch to the car’s fillGasTank(with:)
operate based mostly on the given automobiles
array.
Outline a Generic Parameter Sort
What we making an attempt to attain may appears easy at first, however after we begin coding, we’ll stumble upon our first drawback:
Since various kinds of automobiles would require completely different sorts of gasoline, we should create a generic protocol to characterize each Gasoline
and Diesel
. Let’s go forward and do this.
The Gas
protocol is only a easy protocol consisting of an related kind named FuelType
, and a static buy()
operate. Discover how we constrain FuelType
to all the time equal to the kind that conforms to the Gas
protocol. This constraint is essential to ensure that the compiler to find out the concrete kind returned by the static buy()
operate.
Subsequent up, let’s conform each Gasoline
and Diesel
to the Gas
protocol.
On prime of that, we additionally want to make sure that the Automobile
protocol’s FuelType
is a kind that conforms to the Gas
protocol.
“any” to “some” Conversion
With the Gas
protocol and all different associated modifications in place, we will now revisit the fillAllGasTank(for:)
operate and replace it accordingly.
Within the above code, discover how we leverage the car’s gasoline kind to get an occasion of the Gas
concrete kind, in order that we will cross it into the fillGasTank(with:)
operate.
Sadly, if we attempt to compile our code, we’ll stumble upon our 2nd drawback: “Member ‘fillGasTank’ can’t be used on worth of kind ‘any Automobile’; think about using a generic constraint as a substitute”. What does that imply?
With the intention to perceive the error that we’re getting, let’s have a fast recap on what are the variations between the some
and any
key phrase.
As illustrated within the above picture, the underlying concrete kind of an existential kind is being wrapped inside a field. Due to this fact, the compiler is prohibiting us from accessing the fillGasTank(with:)
operate. To go about this, we should first convert (unbox) the existential kind to an opaque kind earlier than accessing the fillGasTank(with:)
operate.
Happily, Apple has made the conversion (unboxing) course of extraordinarily straightforward in Swift 5.7. All we have to do is to cross the existential kind to a operate that accepts an opaque kind and the conversion will occur routinely.
With that, we will now compile and execute our code with none error.
Be happy to seize the complete pattern code here if you wish to strive it out your self.