[swift-evolution] [Review] SE-0026 Abstract classes and methods

Brent Royal-Gordon brent at architechies.com
Fri Mar 4 01:45:14 CST 2016

> For modeling subtype requirements we would need the ability to declare protocol members with reduced access scope like private or internal and hopefully protected, as subtype requirements most often are not public.

I've spoken about this elsewhere, but:

- For both abstract classes and protocols, all required/abstract members need to be visible everywhere you're permitted to conform/inherit.
- There is currently no way in Swift to decouple a protocol's/class's visibility from the ability to conform to/inherit from it, so neither construct can currently offer this feature.
- However, this feature is likely to come at least for classes as part of resiliency. I think it's a good idea for protocols, too.

>> Protocols don't operate entirely within the class hierarchy, but Swift's type system is broader than just a class hierarchy. In the context of the entire type (directed acyclic) graph, they play the same role of enforcing requirements on subtypes. And with the proper features in place, that's all we really need.
> If you argue that the type graph should governed by protocols only, then we should think about whether it makes sense to take classes (and structs, enums) out of that completely, i.e. these do not define types and classes just provide implementation inheritance. Protocols could then even have their own namespace solving some naming issues. But I'm note sure whether that's really desirable. If not then IMO classes should have comparable capabilities to protocols with regards to shaping the type graph and not be second class citizens.

I don't think that the type graph should be governed entirely by protocols, and that structs, enums, and classes should be second-class citizens at the periphery of a graph of protocols. But I *do* think that this feature does not necessarily need to be implemented in classes.

In many languages, the class hierarchy is all there is, so of course the only way to solve the abstract class use cases is within the class hierarchy. But in Swift, the class hierarchy lives within a larger type graph, and that type graph already includes entities which are quite similar to abstract classes. I simply think that our preferred solution should be to extend the existing feature, rather than duplicating (parts of) it within the class hierarchy.

From my perspective, abstract classes have five defining traits:

1. They cannot be instantiated.
2. They impose requirements on their subclasses.
3. They provide a concrete implementation (which can use those requirements).
4. They anchor the class to the class hierarchy.
5. They can participate in inheritance by overriding and being overridden.

Protocols implement #1, #2, and (much of) #3; current Swift classes implement #3, #4, and #5.

But here's the thing: if we enhance protocols with #4 and #5, *all protocols* become more capable. For instance, if we allow protocol extensions to override superclass methods, that could *also* make conditional extensions more powerful.

	extension MyProtocol where Self: SomeClass {
		override func aMethod() {
			// Woohoo!

If we instead add abstract classes to classes...well, that's nice for when you want to write an abstract class, but it doesn't improve anything else.

The protocol route is off the beaten path, and it would take longer to develop. But I think it has significant benefits:

- It reuses an existing construct which already plays a similar role.
- By reusing that existing construct, it automatically gets useful features (like associated types) which there are no plans to provide with abstract classes.
- It enhances those constructs with new features that may be useful even for other use cases.
- It can be built out incrementally.
- When fully built, it will permit things that abstract classes don't (like inheriting from a subclass of the required class, rather than from the required class directly).

Abstract classes are (likely*) faster to add, and they're the more common solution. But if we think the protocol solution will do more good in the long run, I don't think this use case is so urgent that we can't afford to wait for something better.

* I say "possibly" because, as I pointed out in my review, SE-0026 is a very incomplete proposal and there are several significant details which it doesn't specify clearly.

Brent Royal-Gordon

More information about the swift-evolution mailing list