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

Dietmar Planitzer dplanitzer at q.com
Thu Mar 3 22:26:20 CST 2016


> What is your evaluation of the proposal?

I am in favor of the proposal. However the “Detailed design” section could use some more clarifications:

1) Eg are abstract let’s allowed?

abstract let: String

2) what about abstract class and static methods?

3) should it be possible to import existing ObjC classes which are effectively abstract classes as true abstract classes? Eg:

- add an attribute on the ObjC side which would make it possible to mark classes like NSObject, NSResponder, NSGestureRecognizer, etc as abstract classes. This attribute would have no semantic significance in ObjC.

- those classes would come across into Swift as “abstract class”

This would make it possible to mark classes in the OS frameworks which are effectively abstract classes as such. This would be another stepping stone towards making the use of the existing Cocoa APIs more Swift-like, safer and less error-prone while preserving binary backward-compatibility to the existing ObjC implementation.

4) how will abstract classes which are marked with the @objc attribute or which derive directly or indirectly from NSObject be treated from the ObjC-side?

@objc abstract class Foo {
}

how does the ObjC side look? Would this be exported as just a regular ObjC class? Would it be marked with an attribute as mentioned in the previous bullet point?


> Is the problem being addressed significant enough to warrant a change to Swift?


Yes, in fact Swift is hit harder by the lack of abstract classes compared to other languages which have support for abstract classes. The reason why abstract classes make especially sense for Swift is because of:

1) exhaustive switch-case checks for enum values

2) type-based separation of nullable and non-nullable values

It is often nontrivial and may in fact sometimes be impossible to provide a compilable and type correct null-implementation of a method that should be an abstract method but which can not be marked abstract because of the existing lack of abstract classes in Swift.

In the case of (1) a workaround may be to introduced by adding an extra enum case which only exists to enable us to provide a compile-able null-implementation. But by adding the extra case combined with the exhaustiveness check that Swift does for switch-case blocks, we end up spilling an implementation detail into the API of our class which should actually be kept private. Consider the following example class hierarchy which is used by a media app to describe different types of media:

enum MediaType {
 case Photo
 case LivePhoto
 case Video
}


class MediaItem {

 var title: String = “”
 var type: MediaType = ???
}

class PhotoItem : MediaItem {

 …
}


class VideoItem : MediaItem {

 …
}

How are we going to implement MediaItem.type without abstract methods? We are either forced to introduce a special enum case just to make the code compilable or we are forced to return one of the existing enum cases which is conceptually wrong - the media item is an abstract, unbiased representation of a media item. It is neither a photo, live photo nor a video. If we introduce an extra enum case then every caller of the MediaItem.type property which does a switch-case over the return value will have to handle this extra case.

Let’s revisit the example from the proposal and lets change the property’s type to NSURL to see the problem with (2):

var url : NSURL {

  assert(false,"Must be overridden”)
  return NSURL(fileURLWithPath: “/ignore/this”)
}

We are somewhat “lucky” in this case that we can return a nonsensical URL. It’s bad enough that we have to do this (write nonsensical code just to work around a missing language feature). But things would be even worse if there is no simple initializer available for the struct or object that we want to return. We may be forced to change the type of the property to an optional so that we can return nil instead of a concrete value. This however would change the semantics of the API and is not acceptable in every case.


> Does this proposal fit well with the feel and direction of Swift?

Yes. Swift supports classes. Abstract classes are an established and simple way to describe a partially implemented class and no better solution has been presented on this mailing list that would improve on the concept of abstract classes while not adding additional burden, complexity and potential confusion for the language user.

One recurring suggestion has been to use protocols as a replacement for abstract classes and to extend them with eg support for state so that they can be used as a replacement for abstract classes. None of the presented protocol-based solutions have been convincing.

Abstract classes support a number of important properties:

- they can be derived from concrete classes
- they can be derived from other abstract classes
- they support inheritance
- they support interface
- they support implementation
- they support state

Protocols, as they stand today in Swift support:

- inheritance
- interface
- implementation

but they can not be derived from classes nor do they support state. Additionally, Swift protocols have a number of design problems and are already a major source of confusion for language users. Eg the discrepancy in dispatch behavior between methods defined in the protocol proper and a protocol extension has been cited numerous times as a very confusing and surprising aspect of Swift protocols. A number of other examples of problems can be found in the thread "[Completing Generics] Completing protocol	extension diagnostics”.

Finally, adding state to protocols. Once we add state to protocols, we have moved protocols so close to the semantics of classes that we have effectively turned them into a second kind of class. Protocols are already confusing enough as they are today since they already cover a number of different aspects and we should not end up in a situation where protocols will be turned into a kitchen-sink that is forced to suck up everyone’s personal favorite language feature.


> If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

Compares well to Java and C++.


> How much effort did you put into your review? A glance, a quick reading, or an in-depth study?


I’ve read the proposal and the related discussion thread. I’ve been using languages with and without abstract classes.


Regards,

Dietmar Planitzer


More information about the swift-evolution mailing list