Swift Quiz
Last week, we introduced a fun new format on Twitter, in collaboration with Ahmet Yalcinkaya: Swift Quiz.
In these one day Swift polls, we hope to showcase Swift questions with non-straightforward answers. Some will be practically relevant, and others will lean towards the more obscure end of what you can do in Swift. In any case, we hope they get you thinking for a moment. The next quiz will be up soon! 😀
Last week, we defined a protocol with a single required method, but two methods in an extension:
protocol Drawing {
func render()
}
extension Drawing {
func circle() { print("protocol") }
func render() { circle() }
}
We then created a type SVG
which conforms to the protocol. It also adds a custom implementation of circle
:
class SVG: Drawing {
func circle() { print("class") }
}
The output of calling render
on an instance of SVG
might be surprising at first:
SVG().render()
// prints "protocol"
Although we've defined a circle
method on SVG
, render
doesn't call it.
There's a good reason for this: since we didn't define circle
as part of the protocol's customization points, circle
cannot be customized by types that conform to the protocol. In other words, the call to circle
from within render
is statically dispatched.
Whether this is intended behavior or not depends on what you're shooting for. Sometimes it makes sense to have a method in a protocol extension that cannot be customized, for example, if it's a convenience method providing some functionality on top of the protocol's requirements. However, if we want to allow custom implementations of circle
, we need to add it to the protocol:
protocol Drawing {
func render()
func circle()
}
Methods declared in the protocol are dynamically dispatched. In this example, the implementation of the circle
method that is called will be decided at runtime. We can still have our default implementation in the protocol extension, but we implement a custom version for a specific type conforming to the protocol. This is exactly what the standard library does in many of the collection protocols, and most of the time, it's a good idea for our own protocols as well.
There is a great deal more to say about this topic, and a short post can only begin to hint in that direction. For an in-depth look at all the features of Swift's protocols — protocol extensions, associated types, type erasers and existentials — we'd recommend reading our book, Advanced Swift.
To take part in the Swift Quiz, follow us on Twitter, or check out the archive.