Protocols, Default Implementations and Class Inheritance

Say you have the following setup:

  • A protocol named Doable that defines the doSomething() method.
  • A default implementation for the doSomething() method in a protocol extension.
  • A base class that conforms to Doable, but does not implement the doSomething() method itself.
  • A sub-class inheriting from the base class which provides a custom implementation of the doSomething() method.
  • An array of mixed base and subclass instances that is type [Doable].

The results of invoking doSomething() on all elements of the array may surprise you. When the for loop / reduce / whatever invokes doSomething() on a member of the array which is a subclass, you will not get the subclass’ custom implementation. Instead, you will get the default implementation!

When the runtime goes looking for doSomething() on the current object (of type Doable) in the loop, it looks to the object which actually conforms to the Doable protocol, which is the base class. The runtime checks to see if the class implements the method, and when it sees that the base class does not, it falls back to the default implementation, rather than seeing if the subclass implements it. Apparently, the subclass is only checked in instances where it is overriding a method explicitly defined on its superclass.

So, the solution is actually quite simple:

  • Provide an implementation of doSomething() on the base class. It can just be a duplicate of the default implementation, if that’s the behavior you want for it.
  • Change the subclass’ doSomething() implementation to include an override declaration.

That’s it! The next time you run your loop, the sub-class will have it’s doSomething() method called. I made a playground for you to check this out (turn on documentation rendering):