[swift-evolution] Final by default for classes and methods

Javier Soto javier.api at gmail.com
Thu Dec 17 17:46:00 CST 2015


Does it seem like there's enough interesest in this proposal? If so, what
would be the next steps? Should I go ahead and create a PR on the evolution
repo, describing the proposal version that Joe suggested, with classes
closed for inheritance by default outside of a module?

Thanks!

On Tue, Dec 8, 2015 at 7:40 AM Matthew Johnson via swift-evolution <
swift-evolution at swift.org> wrote:

> I understand the rationale, I just disagree with it.
>
> IMO adding a keyword to state your intention for inheritance is not a
> significant obstacle to prototyping and is not artificial bookkeeping.  I
> really don't understand how this would conflict with "consequence-free"
> rapid development.  It is a good thing to require people to stop and think
> before using inheritance.  Often there is a more appropriate alternative.
>
> The assumption that it is straightforward to fix problems within a module
> if you later decide you made a mistake is true in some respects but not in
> others.  It is not uncommon for apps to be monolithic rather than being
> well factored into separate modules, with many developers contributing and
> the team changing over time.  While this is not ideal it is reality.
>
> When you have the full source it is certainly *possible* to solve any
> problem but it is often not straightforward at all.  Here is an example of
> a real-work scenario app developers might walk into:
>
> 1) A class is developed without subclassing in mind by one developer.
> 2) After the original developer is gone another developer adds some
> subclasses without stopping to think about whether the original developer
> designed for subclassing, thereby introducing subtle bugs into the app.
> 3) After the second developer is gone the bugs are discovered, but by this
> time there are nontrivial dependencies on the subclasses.
> 4) A third developer who probably has little or no context for the
> decisions made by previous developers is tasked with fixing the bugs.
>
> This can be quite a knot to untangle, especially if there are problems
> modifying the superclass to properly support the subclasses (maybe this
> breaks the contract the superclass has with its original clients).
>
> It may have been possible to avoid the whole mess if the second developer
> was required to add 'inheritable' and 'overrideable' keywords or similar.
> They are already required to revisit the source of it while adding the
> keywords which may lead to consideration of whether the implementation is
> sufficient to support inheritance in their currently intended manner.
>
> Implementation inheritance is a blunt tool that often leads to
> unanticipated problems.  IMO a modern language should steer developers away
> from it and strive to reduce the cases where it is necessary or more
> convenient.  Making final the default would help to do this.
>
> Supporting sealed classes and methods that can only be subclassed or
> overridden within the same module is not in conflict with final by
> default.  Both are good ideas IMO and I would like to see both in Swift.
>
> I hope the core team is willing to revisit this decision with community
> input.  If not I will let it go, although I doubt I will ever agree with
> the current decision.
>
> Matthew
>
> Sent from my iPad
>
> On Dec 7, 2015, at 10:30 PM, John McCall <rjmccall at apple.com> wrote:
>
> >>> On Dec 7, 2015, at 7:18 PM, Matthew Johnson via swift-evolution <
> swift-evolution at swift.org> wrote:
> >>> Defaults of public sealed/final classes and final methods on a class
> by default are a tougher call. Either way you may have design issues go
> unnoticed until someone needs to subclass to get the behavior they want. So
> when you reach that point, should the system error on the side of rigid
> safety or dangerous flexibility?
> >>
> >> This is a nice summary of the tradeoff.  I strongly prefer safety
> myself and I believe the preference for safety fits well with the overall
> direction of Swift.  If a library author discovers a design oversight and
> later decides they should have allowed for additional flexibility it is
> straightforward to allow for this without breaking existing client code.
> >>
> >> Many of the examples cited in argument against final by default have to
> do with working around library or framework bugs.  I understand the
> motivation to preserve this flexibility bur don't believe bug workarounds
> are a good way to make language design decisions. I also believe use of
> subclasses and overrides in ways the library author may not have intended
> to is a fragile technique that is likely to eventually cause as many
> problems as it solves.  I have been programming a long time and have never
> run into a case where this technique was the only way or even the best way
> to accomplish the task at hand.
> >>
> >> One additional motivation for making final the default that has not
> been discussed yet is the drive towards making Swift a protocol oriented
> language.  IMO protocols should be the first tool considered when dynamic
> polymorphism is necessary.  Inheritance should be reserved for cases where
> other approaches won't work (and we should seek to reduce the number of
> problems where that is the case).  Making final the default for classes and
> methods would provide a subtle (or maybe not so subtle) hint in this
> direction.
> >>
> >> I know the Swift team at Apple put a lot of thought into the defaults
> in Swift.  I agree with most of them.  Enabling subclassing and overriding
> by default is the one case where I think a significant mistake was made.
> >
> > Our current intent is that public subclassing and overriding will be
> locked down by default, but internal subclassing and overriding will not
> be.  I believe that this strikes the right balance, and moreover that it is
> consistent with the general language approach to code evolution, which is
> to promote “consequence-free” rapid development by:
> >
> >  (1) avoiding artificial bookkeeping obstacles while you’re hacking up
> the initial implementation of a module, but
> >
> >  (2) not letting that initial implementation make implicit source and
> binary compatibility promises to code outside of the module and
> >
> >  (3) providing good language tools for incrementally building those
> initial prototype interfaces into stronger internal abstractions.
> >
> > All the hard limitations in the defaults are tied to the module boundary
> because we assume that it’s straightforward to fix any problems within the
> module if/when you decided you made a mistake earlier.
> >
> > So, okay, a class is subclassable by default, and it wasn’t really
> designed for that, and now there are subclasses in the module which are
> causing problems.  As long as nobody's changed the default (which they
> could have done carelessly in either case, but are much less likely to do
> if it’s only necessary to make an external subclass), all of those
> subclasses will still be within the module, and you still have free rein to
> correct that initial design mistake.
> >
> > John.
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-- 
Javier Soto
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151217/977b5178/attachment.html>


More information about the swift-evolution mailing list