[Review] SE-0117: Default classes to be non-subclassable publicly


(Jakub Suder) #1

What is your evaluation of the proposal?

Strong -1 from me.

I agree that subclassing library classes that were not explicitly planned
to be subclassed might sometimes lead to bugs. But just because a technique
or feature of a language allows you to sometimes make mistakes, it doesn't
mean it should be completely disallowed. By this logic, we'd have to remove
all instances of "!" any anything related to pointers from Swift. It's
possible for a feature to allow you to shoot yourself in the foot, and
still be useful at the same time.

We've removed things like C-style for loops or "if object {" shorthand from
Swift, because we have cleaner ways of achieving the same goals in a
different way, so it was safe to remove them without making the language
less powerful. But here we would be removing a feature for which there is
no workaround. If I need to override some methods from a binary library or
SDK that I use in my app (e.g. Crashlytics, Zendesk - yes, these are ObjC
libraries, but I'm speaking about the future), in order to work around some
bugs, customize or adapt the behavior to my app (e.g. UI styling,
copywriting, i18n), then there's no other way to do achieve this, other
than rewriting the whole thing from scratch. Even if I do have access to
the source code, keeping your extensions in a subclass in your app is a
much cleaner solution that hacking the library code directly (and getting
merge conflicts later). One day, Apple system frameworks will also be
written in Swift, and this change will make it harder to use them.

Of course, the above is only a problem if the class hasn't been marked as
subclassable. But I'm afraid that in most cases it won't be, even if it
could be, simply because:

1) the author hasn't foreseen I'd need this (how could they foresee every
possible use case and requirement? if they had known what I'm going to
need, I wouldn't need to write a subclass in the first place)

2) or, more likely, they just didn't remember about this feature or didn't
realize at all that they need to add this subclassable keyword to make this
possible. Or they did, but they forgot to add it to some new code.

The proposed 'subclassable' and 'overridable' keywords would also introduce
a lot of noise to the library code, if the author wanted to make most or
all of their code extensible. A single 'open' keyword would be preferred,
and adding it only to the class and not the methods (marking class as open
makes whole class and its methods non-final) would be even better, since it
would make it more likely library authors would actually use it (though
still only a "lesser evil").

As for the performance aspect - I don't think a minor speedup should be a
reason to remove a useful feature from the language, it would be most
likely a case of premature optimization. If necessary, you can always mark
a critical class as final if profiling shows that it's being called all the
time, and leave all the other classes open by default.

Is the problem being addressed significant enough to warrant a change to

Swift?

I don't think the problem is significant, and I'm afraid the proposed
solution is worse than the problem itself.

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

I don't feel qualified to answer this.

If you have used other languages or libraries with a similar feature, how

do you feel that this proposal compares to those?

I've used Ruby and JavaScript for many years each, and ObjC for a few
years. In my opinion, all three give the developer much more power when it
comes to using code in creative and unplanned ways when that's what you
need to achieve your goals, than Swift does currently. That's especially
the case with the first two - ObjC already felt too restrictive in many
ways for me.

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 skimmed through the responses thread.

Kuba