Follow up: overridable members in extension

This is in reference to:

swift-evolution/nnnn-overridable-members-in-extensions.md at overridable-members-in-extensions · jrose-apple/swift-evolution · GitHub <https://github.com/jrose-apple/swift-evolution/blob/overridable-members-in-extensions/proposals/nnnn-overridable-members-in-extensions.md&gt;

The limitation of not being able to override methods introduced by an extension to a parent class within a child class is pretty significant and I would propose that we find and explore a way to allow such while supporting the original intent of this limitation.

This has become a problem for a project I’m working on when transitioning to Swift 4. Here is a description of the problem:

Our major application has a class hierarchy of financial transaction types similar to the following:

Transaction
Billable
  Taxable
    Purchase
      Bill
      ...
    Sales
      Estimate
      Invoice
      ...
Deposit
Journal Entry
...

Etc.

These are currently implemented in ObjC but have been extended in Swift. So there are the original transaction classes in ObjC with extensions in Swift.

This combination of ObjC/Swift has been done to support modern presentation in iOS, essentially following the MVVM approach. ‘Transaction’ has been extended and specifies the various View Model methods each of its child classes must implement. There are default implementations going down the Swift inheritance tree but each child can customize (override) those methods and, many times, calls the inherited method.

For instance, the header presentation for each transaction shows a date and total amount but each subclass has other header elements to show: all ‘Billable’ transactions show a name and due date. Going down the chain, each final child class provides the explicit title to be shown in the header, such as ‘Invoice’. Further, the background color of the header is set based on the status of the transaction. Of course, some transactions only have one state, the default state provided by a parent class.

With this said, eliminating the ability to extend ‘Transaction’ and then override down in each subclass’s extension was very convenient. Under the current Swift 4 restrictions we will have to either reimplement the class extensions in the original model (which will not be done because the model must be ignorant of any presentation-specific requirements) or everything will have to be moved up into a single Transaction extension and use a switch structure based on dynamic casting as discussed in the article mentioned way above (which corrupts ‘Transaction’ by requiring it to know intimate details about its children, grandchildren, etc.).

It would be nice if there were some protocol-based mechanism where a parent class could adopt that protocol (not in the original class declaration, of course, since UI-related methods should not be polluting the model layer) and then some extension-like mechanism allowing child classes to provide their specific implementation of those methods.

Of course, one potential approach would be to create a similar class structure to the model’s Transaction structure but where the new class ‘owns’ the instance of the raw transaction. Say, something like TransactionVM with BillableVM, PurchaseVM, etc. Of course, for each different type of transaction presentation (full details, brief details, list summary, etc.) there would need to be yet another ‘container’ class structure. And they wouldn’t be able to inherit from one another for the same reason I’m blathering on here.

Of course, if there is already a more appropriate approach for solving a problem like this, please do not hesitate to correct me as I still consider myself pretty ‘young’ with Swift 4.

Mike