Swift protocols can provide default implementations for functions and computed properties by adding extensions to them. I've done that plenty of times. It is my understanding that the default implementation is only used as a "fallback": It's executed when a type conforms to the protocol but doesn't provide its own implementation.
At least that's how I read The Swift Programming Language guide:
If a conforming type provides its own implementation of a required method or property, that implementation will be used instead of the one provided by the extension.
Now I ran into a situation where my custom type that implements a certain protocol does provide an implementation for a particular function but it's not executed — the implementation defined in the protocol extension is executed instead.
As an example, I define a protocol Movable
that has a function move(to:)
and an extension that provides a default implementation for this function:
protocol Movable {
func move(to point: CGPoint)
}
extension Movable {
func move(to point: CGPoint = CGPoint(x: 0, y: 0)) {
print("Moving to origin: \(point)")
}
}
Next, I define a Car
class that conforms to Movable
but provides its own implementation for the move(to:)
function:
class Car: Movable {
func move(to point: CGPoint = CGPoint(x: 0, y: 0)) {
print("Moving to point: \(point)")
}
}
Now I create a new Car
and downcast it as a Movable
:
let castedCar = Car() as Movable
Depending on whether I pass a value for the optional parameter point
I observe two distinct behaviors:
When passing a point for the optional parameter
→ the
Car
's implementation is called:castedCar.move(to: CGPoint(x: 20, y: 10))
Output:
Moving to point: (20.0, 10.0)
When I invoke the
move()
function without providing a value for the optional parameter theCar
's implementation is ignored and→ the
Movable
protocol's default implementation is called instead:castedCar.move()
Output:
Moving to origin: (0.0, 0.0)