These arguments are definitely compelling. I would have to agree with this 
strongly. Very fair reasoning.

> On 20 Dec 2015, at 2:21 PM, Jordan Rose via swift-evolution 
> <[email protected]> wrote:
> 
> 
>> On Dec 7, 2015, at 20:30 , John McCall via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 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.
> 
> I think John summarized my position very well, so of course I'm going to come 
> in here and add more stuff. :-)
> 
> In working on the design for library evolution support ("resilience"), we've 
> come across a number of cases of "should a library author be able to change 
> this when they release v2 of their library?" Many times, the answer is it's 
> possible to do something in one direction, but not at all safe to go the 
> other way. For example, you can always add public methods to a class, but you 
> can't remove public methods because you don't know who's calling them. You 
> can mark them deprecated, but that doesn't help with any client apps that 
> have already been compiled and shipped.
> 
> One of the things that came up was "can you add 'final' to a class?" And of 
> course you can't, because you don't know who may have already subclassed it. 
> That's very unfortunate for a library author who simply forgot to add 'final' 
> when they were first writing the class.
> 
> The interesting thing about this is that the "error of omission"—of failing 
> to think about whether a class should be final—is worse than the alternative. 
> Ignoring optimizations for a minute, a class that starts out 'final' can 
> certainly become non-final later; it doesn't change how the class is 
> currently used.* For a lot of library evolution questions, this is the 
> preferred answer: the default should be safe, and the designer of the class 
> can choose to be more aggressive later.
> 
> This is also the guiding principle behind the behavior of 'public'. A number 
> of people have asked for members of a public struct to implicitly be made 
> public. But here again the "error of omission" is problematic: a helper 
> function you add for your own use may now be depended on by client apps far 
> and wide, just because you forgot to customize the access control. So Swift 
> says you should explicitly consider the public interface of every type.
> 
> Why 'sealed' instead of 'final' as the default? Because inheritance is 
> useful, and within your own code having to opt into it starts to feel like 
> unnecessary clutter. This is a trade-off, just like defaulting to 'internal' 
> over 'private', but it's one that keeps life easy for a single developer with 
> a single module: their app. (And the compiler can still do useful things with 
> non-final classes if it can see the entire class hierarchy.) Additionally, 
> limiting inheritance to the current file (a la 'private') is also potentially 
> useful.
> 
> This direction separates "limiting inheritance/overrides" from "has no 
> subclasses/overrides". The former is about defining the limits of your API; 
> the latter is a promise that can be used for performance. I think that's a 
> good thing.
> 
> Jordan
> 
> * Even without optimizations a 'final' class cannot safely drop the 'final'. 
> If a class is 'final', it may have additional 'required' initializers added 
> in extensions.
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to