Actually, Curt, not that I'm in favor of this proposal, but you inspired an interesting thought--I think that if extensions were more powerful (e.g. stored properties), then having closed classes by default might not be such a big deal. What's the difference between using a `MyViewController` subclass throughout your app to hack around Cocoa's limitations and writing an extension for UIViewController to use app-wide? The only significant difference would probably be a couple fewer hackarounds in the UIViewController case.
Of course, it would break a lot of existing code *without a way to automatically migrate it*. That's a deal breaker for me. On Sat, Dec 19, 2015 at 10:09 PM Curt Clifton via swift-evolution < swift-evolution@swift.org> wrote: > I'm not sure how many minuses I have to give, but I'd give them all to > this proposal. > > Anyone who tries to ship products on release day of Apple's operating > system updates spends most of August and September writing horrible hacks > so that their users are insulated from OS bugs as much as possible. All > software has bugs, frameworks included. Please don't take away our tools > for working around those bugs. Making classes final by default assumes a > level of perfection on the part of framework developers that is not > achievable. > > Yes, subclassing a class that wasn't designed to be subclassed has serious > risks. Thoughtful developers sometimes take on those risks in order to > serve their customers. > > Frankly, I think having `final` in the language at all is a mistake. While > I agree that we should prefer composition to inheritance*, declaring things > final is hubris. The only reasonable use case I've seen is for > optimization, but that smacks of developers serving the compiler rather > than the converse. Bringing an analog of NS_REQUIRES_SUPER to Swift would > be most welcome; that's as far as I'd go down the path of dictating > framework usage. > > Cheers, > > Curt > > *- and am thrilled with the property behaviors proposal for this use case > > > On Dec 17, 2015, at 5:55 PM, Joe Groff via swift-evolution < > swift-evolution@swift.org> wrote: > > > On Dec 17, 2015, at 5:41 PM, Rod Brown via swift-evolution < > swift-evolution@swift.org> wrote: > > My opinion is -1 on this proposal. Classes seem by design to intrinsically > support subclassing. > > What if one framework provider thinks “you won’t need to subclass this > ever” but didn’t realise your use case for doing so, and didn’t add the > keyword? When multiple developers come at things from different angles, the > invariable situation ends with use cases each didn’t realise. Allowing > subclassing by default seems to mitigate this risk at least for the most > part. > > > Frameworks change, and if the framework author didn't anticipate your use > case for subclassing, they almost certainly aren't going to anticipate it > while evolving their implementation and will likely break your code. Robust > subclassability requires conscious design just like all other aspects of > API design. > > -Joe > > I think this definitely comes under the banner of “this would be nice” > without realising the fact you’d be shooting yourself in the foot when > someone doesn’t add the keyword in other frameworks and you’re annoyed you > can’t add it. > > > On 18 Dec 2015, at 10:46 AM, Javier Soto via swift-evolution < > swift-evolution@swift.org> wrote: > > 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@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 <rjmcc...@apple.com> wrote: >> >> >>> On Dec 7, 2015, at 7:18 PM, Matthew Johnson via swift-evolution < >> swift-evolution@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@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >> > -- > Javier Soto _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution