<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 23, 2015, at 11:36 AM, Paul Cantrell &lt;<a href="mailto:cantrell@pobox.com" class="">cantrell@pobox.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">An omission in Matthey’s summary:</div><div class=""><br class=""></div><div class="">____</div><div class=""><br class=""></div><div class=""><div class="">While tentatively supporting the proposal, some on the thread express a concern about its implications:</div><div class=""><br class=""></div><div class=""><div class="" style="font-family: HelveticaNeue;"><b class="">A shift toward more defensive programming in libraries prevents ad hoc w</b><span class=""><b class="">orkarounds in client projects</b></span><b class="">.</b>&nbsp;Clients of Objective-C libraries commonly work around bugs, shortcomings, and feature gaps with swizzling and dubious subclassing. These hacks, while undesirable in principle, are part of the current Apple development culture and ecosystem. Mechanisms that prevent such hacks, including but not limited to “final by default” or “sealed by default,” must be accompanied by a shift in how library authors think about their API design, and how they interact with their community. This shift will impose a new burden on library authors.</div></div></div><div class=""><br class=""></div><div class="">___</div><div class=""><br class=""></div><div class="">Matthew assures me off-list that this is distinct from his #1, which was meant only as a comment on Apple’s policies being independent of this proposal.</div><div class=""><br class=""></div></div></div></blockquote><div><br class=""></div><div>I want to thank Paul for pointing out an omission in the list I posted this morning. &nbsp;As Paul mentions the first item on my list was focused on Apple frameworks and the fact that Swift’s default doesn’t prevent Apple from adopting a policy of making explicit design decisions regarding inheritability of their framework classes.</div><div><br class=""></div><div>Paul points out that many people have similar concerns about how the default might impact 3rd party frameworks and libraries. &nbsp;In 2015 this <i class="">usually&nbsp;</i>means open source libraries. &nbsp;</div><div><br class=""></div><div>I think it is worth repeating an important point that has been stated many times by many individuals in this thread: a responsible library author considers inheritability as part of the API contract. &nbsp;If they have not planned for it they should not allow it. &nbsp;This is true regardless of what the default of the language is and whether the framework is from Apple or an open source library.</div><div><br class=""></div><div>That said, if a developer runs into an issue with an open source library that has a final class they would like to subclass there are several options available:</div><div><br class=""></div><div>1. If the need to subclass is due to a bug, file a bug report or fix it and contribute a patch. &nbsp;No subclassing necessary.</div><div>2. If you view the `final` status as a design error get in touch with the authors and discuss an enhancement.</div><div>3. If the authors agree in theory, but don’t want to do the implementation work of designing a proper superclass, do the work yourself and make a contribution.</div><div>4. If the authors disagree they would probably be using final if it wasn’t the default. &nbsp;You can still fork the project and make any changes you desire, including allowing inheritance. &nbsp;You can even allow inheritance without really thinking about whether the superclass is properly designed to support it or not if you really want to. &nbsp;Nobody is stopping you or limiting your flexibility when it comes to open source projects!</div><div><br class=""></div><div>In reality closed source, binary only libraries from 3rd parties are the exception, not the norm. &nbsp;Bad experiences with closed source, binary libraries (some have mentioned C++) in the past aren’t really applicable to future experiences with <i class="">open source </i>libraries.</div><div><br class=""></div><div>Of course closed source libraries do still exist, usually in the form of an SDK for a third party service. &nbsp;I wonder how many of those expressing the concern about 3rd party libraries are referring to SDKs like this, and if they are, what kinds of issues have been encountered in the past that are motivating the concern. &nbsp;If this is what people are worried about it might help the conversation if you are able to get a little bit more specific with your concerns.</div><div><br class=""></div><div>Matthew</div><div><br class=""></div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Dec 23, 2015, at 9:07 AM, Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: HelveticaNeue; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="">I’ve been following the thread very closely and have noticed six primary arguments against final by default:</div><div class=""><br class=""></div><div class="">1)<span class="Apple-converted-space">&nbsp;</span><b class="">Workarounds for framework “bugs”</b>. &nbsp;I put “bugs” in quotes because I think it is likely that sometimes it is not exactly a bug, but misunderstood or disliked behavior that is being “worked around". &nbsp;No need to rehash this. &nbsp;It’s been beaten to death. &nbsp;It’s also irrelevant as it’s clear that the default is almost certainly going to be at least `sealed`. &nbsp;It’s also irrelevant because Apple’s frameworks are currently written in Objective-C, not Swift, and when Apple begins writing frameworks in Swift they are very likely to be thinking carefully about subclassing as part of the API contract decision.</div><div class=""><br class=""></div><div class="">2)<span class="Apple-converted-space">&nbsp;</span><b class="">Flexibility</b>. &nbsp;If I don’t need inheritance when I first write a type and later realize I do need it, I have to revisit the type and add an `inheritable` annotation later. &nbsp;This is closely related to argument #2 and mostly relevant during prototyping (argument #5). &nbsp;IMO when this scenario arises you<span class="Apple-converted-space">&nbsp;</span><b class="">should</b>&nbsp;have to revisit the original type. &nbsp;If you don’t you are asking for trouble as inheritance was not considered when it was written. &nbsp;Adding an `inheritable` annotation is trivial when compared to the analysis that should be performed when it becomes a superclass.</div><div class=""><br class=""></div><div class="">3)<span class="Apple-converted-space">&nbsp;</span><b class="">Annoyance</b>. &nbsp;Some consider it to be annoying to have to annotate a class declaration in order to inherit from it. &nbsp;People stating this argument either are either writing a lot of superclasses or are so bothered by the need to annotate their type declarations that they avoid `final` and its related benefits when that is really the right thing for their class. &nbsp;For me personally, `final` is the right thing for most classes I write. &nbsp;I also think adding a `final` annotation is the right thing to do if you’re not sure whether it will be a superclass or not. &nbsp;The need to modify the annotation will remind you that you haven’t fully considered inheritance in your design yet.</div><div class=""><br class=""></div><div class="">4)<span class="Apple-converted-space">&nbsp;</span><b class="">Testing</b>. &nbsp;This is solvable with behavior similar to @testable. &nbsp;It should not influence the decision about what the default is for production code.</div><div class=""><br class=""></div><div class="">5)<span class="Apple-converted-space">&nbsp;</span><b class="">Prototyping</b>. &nbsp;This should also not influence the decision about what the default is for production code. &nbsp;I would not have a problem with a prototyping environment allowing `inheritable` by default (maybe a Playground mode?). &nbsp;There could even be a tool that migrates the prototype to a real project and adds the `inheritable` annotation where necessary. &nbsp;Regardless of what happens here, the prototyping problem can and should be solved independently of the production language and should not influence the default is used in and impacts production code.</div><div class=""><br class=""></div><div class="">6)<span class="Apple-converted-space">&nbsp;</span><b class="">Education</b>. &nbsp;There may be some value in allowing inheritance by default in education settings, especially early on. &nbsp;I view this as being quite similar to the prototyping case and again should not have an influence on the default that professionals use in production code.</div><div class=""><br class=""></div><div class="">If I have missed any of the major arguments against making `final` the default please respond with them. &nbsp;I would be happy to add them to the list.</div><div class=""><br class=""></div><div class="">I don’t find any of these arguments compelling. &nbsp;The only one that is really relevant to production code (once you accept the reality of #1) is annoyance which I consider a minor complaint that is definitely not relevant to my code and is likely not relevant to many other people’s code as well. &nbsp;</div><div class=""><br class=""></div><div class="">On the other hand, the argument for `final` as default<span class="Apple-converted-space">&nbsp;</span><b class="">is</b>&nbsp;compelling IMHO. &nbsp;As has been stated many times, inheritance is part of an API contract that needs to be considered as clearly as anything else. &nbsp;This still applies when the API is internal to an app.</div><div class=""><br class=""></div><div class="">Final by default greatly improves our ability to get up to speed on a new codebase quickly and reason about the code:</div><div class=""><br class=""></div><div class="">1) When I look at an unannotated class declaration I<span class="Apple-converted-space">&nbsp;</span><b class="">know</b>&nbsp;there are no subclasses. &nbsp;I don’t have to search the code to look for subclasses. &nbsp;</div><div class="">2) I<span class="Apple-converted-space">&nbsp;</span><b class="">know</b>&nbsp;that where there are superclasses, the author was reminded by the language to consider inheritance. &nbsp;They may have made mistakes in the design of the superclass, but at least the language gave them a subtle reminder that they need to think about it. &nbsp;</div><div class="">3) I also&nbsp;<b class="">know</b>&nbsp;there will not be any subclasses in the future unless someone adds an `inheritable` annotation (in which case they are responsible for considering the implications of that). &nbsp;The `inheritable` annotation also serves as a good prompt for code reviews to consider the implications of that annotation if / when the class becomes an intentional superclass.</div><div class=""><br class=""></div><div class="">Of course all of these advantages also apply to a codebase where I am the sole author and maintainer when I come back to it year or two later and have forgotten some details.</div><div class=""><br class=""></div><div class="">One consideration that has not been definitively established one way or the other is frequency of use. &nbsp;In application code are there usually more classes that are superclasses (or could reasonably be a superclass in the future without additional analysis and design)? &nbsp;Or are there usually more classes that are `final`, effectively final, or<span class="Apple-converted-space">&nbsp;</span><i class="">should</i>&nbsp;be final, at least until further analysis and design has been performed? &nbsp;</div><div class=""><br class=""></div><div class="">In my experience the reality is that the majority of my classes inherit from UIKit classes, but are not themselves superclasses. &nbsp;I don’t claim to speak for anyone else, but I think we would find that to be the most common pattern if we looked at the question closely.</div><div class=""><br class=""></div><div class="">I hope this is a reasonably accurate summary of the positions on both sides of this.</div><div class=""><br class=""></div><div class="">Matthew</div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class="">On Tue, Dec 22, 2015, at 09:03 AM, Paul Cantrell via swift-evolution wrote:<br class=""><blockquote type="cite" class="">Joe’s and Brent’s writeups copied below really get to the heart of this for me. This is a tough question, and I find myself torn. I’m sympathetic to both lines of argument.<br class=""><br class="">It’s not entirely true that “you can never take back” overridability — you can make a breaking API change with a new major version, of course — but it’s a compelling point nonetheless. One default is clearly safer than the other, at least for the library author. “Safe by default” is indeed the Swift MO. (Well, except for array subscripting. And any public API involving tuples, for which any change, even type widening, is a breaking change. And….OK, it’s not absolute, but “safe by default” is the MO 95% of the time.) “Final by default” just seems more Swift-like to me.<br class=""><br class="">Despite that, Joe, I have to agree with Brent on his central point: the perspective that comes from spending a lot of time _writing_ libraries is very different from one who spend more time _using_ them. Yes, UIKit is not going to be rewritten in Swift anytime soon, but Brent is rightly imagining a future where the Swift way is The Way.<br class=""><br class="">I weigh the safety argument against the many long hours I’ve spent beating my head against library behaviors, wishing I could read UIKit’s source code, wishing I could tweak that one little thing that I can’t control, and being grateful for the dubious workaround that saves the day — yes, even when a subsequent OS update breaks it. I know what I’m getting into when I solve a problem with a hack, and if the hack ships, it’s only because I weighed the risks and benefits. We app developers rely on swizzling, dubious subclassing, and (especially) undocumented behavior far more often than any of us would like. It is just part of the reality of making things ship — and an important part of the success of Apple’s app ecosystem.<br class=""><br class="">This debate reminds me of something that often happens when a humans-and-paper process moves to software. When the software starts rigorously enforcing all the rules the humans were theoretically following all along, and it turns out that quite a lot of in-the-moment nuanced human judgement was crucial to making everything work. With nuance removed, things fall apart — and instead of things at last achieving the rigor that seemed so desirable in theory, the process has to explicitly loosen. (At the local coffee shop, a new iPad-based POS system suddenly made it an “uh let me get the manager” moment when I want to get the off-menu half-sized oatmeal I’ve always got for my toddler.)<br class=""><br class="">I’m not totally opposed to final by default. Joe’s arguments sway me in principle. In practice, if Swift does indeed moves us toward “less wiggle room, less hackable” by default, then that wiggle room _will_ have to come from somewhere else: perhaps more open sourcing and more forking, or faster turnaround on fixes from library authors, or a larger portion of time spent by library authors explicitly exposing and documenting customization points. The new effort involved for library authors is nothing to sneeze at.<br class=""><br class="">Cheers,<br class=""><br class="">Paul<br class=""><br class=""><br class=""><blockquote type="cite" class="">On Dec 22, 2015, at 9:46 AM, Joe Groff via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class="">I think a lot of people in this thread are conflating "final by default" or "sealed by default" with "sealed everywhere". No matter what the default is, the frameworks aren't going to suddenly rewrite themselves in Swift with final everything; Objective-C will still be what it is. Furthermore, we're only talking about language defaults; we're not taking away the ability for frameworks to make their classes publicly subclassable or dynamically overrideable. That's a policy decision for framework authors to make. The goal of "sealed by default" is to make sure the language doesn't make promises on the developer's behalf that they weren't ready to keep. ObjC's flexibility is valuable, and Apple definitely takes advantage of it internally all over place; Apple also has an army of compatibility engineers to make sure framework changes work well with existing software. Not every developer can afford that maintenance burden/flexibility tradeoff, though, so that flexibility is something you ought to opt in to. You can always safely add public subclassability and dynamic overrideability in new framework versions, but you can never take them back.<br class=""></blockquote><br class=""><br class=""><blockquote type="cite" class="">On Dec 22, 2015, at 12:31 AM, Brent Royal-Gordon via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class="">Just imagine going through UIKit and marking every class inheritable *by hand*—no cheating with a script—and you'll have some idea of the additional burden you'll be imposing on developers as they write their code. The proposals that every single method should be explicitly marked as overridable are even worse; frankly, I don't think I'd want to use Swift if you forced me to put a `virtual` keyword on every declaration.<br class=""><br class="">I worry that the team's use of Swift to build the standard library, and their close association with teams building OS frameworks, is biasing the language a little bit. I think that, in all likelihood, most Swift code is in individual applications, and most libraries are not published outside of a single team. If I'm right, then most Swift code will probably be quite tolerant of small but technically "breaking" ABI changes, such as making a class `final`, or (as mentioned in another thread) making a closure `@noescape`.<br class=""><br class="">That won't be true of published library code, of course. But published library code is a small minority of the Swift code people will write, and it already will require greater scrutiny and more careful design.<span class="Apple-converted-space">&nbsp;</span><br class=""><br class="">There is already a good opportunity to reflect on whether or not an API should be `final`. It's when you put the `public` keyword on it. I think programmers will have a better, easier time writing their code if, in this case, we put a little bit of trust in them, rather than erecting yet another hoop they must jump through.<br class=""><br class="">Perhaps we could even provide a "strict interfaces" mode that published frameworks can turn on, which would require you to declare the heritability of every class and member. But even that may not be a good idea, because I also suspect that, in the field, most published libraries probably have to be extended in ways the library's author did not expect or anticipate.<span class="Apple-converted-space">&nbsp;</span><br class=""><br class="">This means doing some dangerous overriding, yes. But a UI that breaks after an iOS upgrade is not nearly as dangerous to my business as a three-month delay while I reimplement half of UIKit because someone in Cupertino thought they knew what I need better than I do and turned off—or even worse, *left turned off without a single thought*—subclassing of UIBarButtonItem.<br class=""><br class="">The bottom line is this: Your users like Swift's strictures when they're helpful. *This stricture is not helpful.* Library users don't accidentally subclass things, and with the `override` keyword in Swift, they don't accidentally override them either. And where it truly is important, for safety or for speed, to prevent subclassing, we already have `final`. Making it the default is less safety than suffering.<br class=""></blockquote>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></blockquote>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></div></blockquote></div><br class="" style="font-family: HelveticaNeue; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=zCg-2FSGF9Wk188a6c55kLyEbrj7YhaXxFEHM-2F-2B0YAlzWib-2FCjzoSIFyDmZiwREcQi-2FSDoXqtQqhpp-2FPmCzBPQZ2OLopXTmr9eOG6pQn6reAzBr06KXwbJbEyesBxz69zcu4DsnXgLYrBmadW7pk-2FDV-2FJJeVEMc-2BLs6ED5lL3oR6KHtbfx5kqvbxF5PuPCS6djfdh1En1c-2FsUKp-2FzuFNBTw4RmrAqd5pqR9y3viyF7gSM-3D" alt="" width="1" height="1" border="0" style="font-family: HelveticaNeue; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; height: 1px !important; width: 1px !important; border-width: 0px !important; margin: 0px !important; padding: 0px !important;" class=""><span style="font-family: HelveticaNeue; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class=""><span class="Apple-converted-space">&nbsp;</span>_______________________________________________</span><br style="font-family: HelveticaNeue; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: HelveticaNeue; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">swift-evolution mailing list</span><br style="font-family: HelveticaNeue; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="mailto:swift-evolution@swift.org" style="font-family: HelveticaNeue; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><br style="font-family: HelveticaNeue; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family: HelveticaNeue; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></body></html>