[swift-evolution] [Review] SE-0026 Abstract classes and methods
david at alkaline-solutions.com
Fri Feb 26 15:54:40 CST 2016
> https://github.com/apple/swift-evolution/blob/master/proposals/0026-abstract-classes-and-methods.md <https://github.com/apple/swift-evolution/blob/master/proposals/0026-abstract-classes-and-methods.md>
> • What is your evaluation of the proposal?
> • Is the problem being addressed significant enough to warrant a change to Swift?
The functionality (to allow greater composability of code) is significant enough to warrant a change in swift, but the actual implementation (via abstract classes) is not. I would prefer additional trait/mixin functionality.
> • Does this proposal fit well with the feel and direction of Swift?
While Swift could use more functionality around mixin-like behavior and more sophisticated trait functionality, staying away from class inheritance more often than not results in better code.
Abstract base classes in particular have a strong tendency to become a composability anti-pattern, because you are not defining the behavior of the interacting objects but are requiring a specific form of implementation and specific, often undocumented side-effects.
As an example from the proposal:
The RESTClient abstract base class defined in the proposal has hard-coded a single URL. If I need multiple URLs (say, client side address randomization) then the behavior between var url and performNetworkCall is insufficient. It is likely that other code relying on RESTClient is using the base class name, and not some protocol, so my only hope for working with existing code is to figure out how to make my subclass behave properly when performNetworkCall is defined.
If I was working with RESTClient as a protocol, performNetworkCall would just be a required method to implement. I could choose to implement it however I want to. Because of the abstract base class, I need to worry about whether some other functionality in the base class I am forced to use for interoperability will conflict with my new definition. And of course, var url is still meaningless in my implementation, so I better just have it return a dummy value.
To be fair, RESTClient is a placeholder. It could be better designed if it were part of a system and not an example in a proposal.
However, this is the problem with abstract base classes - they always could be hypothetically designed better. Their goal is usually to provide some implementation details while allowing flexibility of a third party to extend with the actual functionality and behavior needed. But it is very difficult (perhaps impossible) to on one hand remain flexible while on the other hand dictate implementation details both as side effects required in your system and for convenience. Sure, abstract classes can always be better designed - when considered in retrospect. Thats because the author of the abstract class has gained experience and now understands some of the flexibility other developers required in implementation!
Better to define protocols, and provide implementations of those protocols based on the functionality you know people will need. Even more so if you can use traits to define behavior you commonly expect developers to need, such that they can take or leave such behaviors as they see fit.
> • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
In my professional experience, I have a tough time thinking of any abstract base class which I haven’t considered a poor design choice. That abstract base classes are often the simplest design choice makes me believe this feature would be abused.
Java is the language where I’ve hit the most abstract base class requirements. I have nothing to suggest be salvaged from there in this regard.
Ruby has both class inheritance and mix-in support, and both are used extensively. Class inheritance in Ruby is saved by late-bound typing - it is considered bad form to test that your code was given a specific type, instead encouraging either coercion of types or duck typing. Otherwise, the lack of protocols in the language would make developing code very difficult.
Design (including language design) is not just about what is there, but what is not. I feel promoting traits over abstract classes this is another opportunity for the Swift language to promote better code.
It is also worth noting that Objective-C does not support abstract classes, and this proposal did not attempt to define how that would be rectified as part of interoperability:
- Would abstract classes need also be defined in Objective-C?
- Does the entire hierarchy at and defending from the abstract class become un-exposable to Objective-C, or just the abstract classes themselves?
- If the initializable classes in the hierarchy are exposed to Objective-C, are the abstract classes exposed via e.g. +(Class) superclass; ?
> • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
Participated in the discussion, in-depth study.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the swift-evolution