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

The proposal (and additional comments) explain this point fairly well. Usually, it makes sense to be overridable only for few select members — and compiler can’t easily figure out which entry points these are as the API invariants are not explicit. By making members sealed by default, the API contracts are made more clear. Second (and a very important reason) is performance — if everything is open by default, the compiler can’t devirtualize property accessors even though it would be appropriate most of the time. The compiler can infer the ‚final‘ status of definitions within a module easily and optimise accordingly, which wot work if these definitions can be overridden externally. To put it differently, its much easier for the compiler to determine what can be safely considered final than what can be safely considered sealed. The design choices in the proposal follow naturally from these considerations.

The final keyword still has its use, although I think its utility will be somewhat diminished after this proposal. You can still use it for things that can’t be overridden internally. Like classes that are intended only to be used as ‚structs with reference semantics‘.

— T

···

On 16 Jul 2016, at 18:05, Jose Cheyo Jimenez via swift-evolution <swift-evolution@swift.org> wrote:

I agree with Kevin Ballard on being open by default for methods/ properties http://article.gmane.org/gmane.comp.lang.swift.evolution/23467/

If we are open by default for methods/properties then we could simplify things by just using final for methods that need to be sealed; I don’t see the need to have sealed methods/properties outside of the module ONLY.

Regards
(From mobile)

Regards
(From mobile)

Hello Swift community,

The second review of "SE-0117: Default classes to be non-subclassable publicly" begins now and runs through July 22. The proposal is available here:

  https://github.com/apple/swift-evolution/blob/master/proposals/0117-non-public-subclassable-by-default.md

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

  https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to the review manager.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and contribute to the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

  * What is your evaluation of the proposal?

Part of a series of increasingly compelling arguments for switching other languages for writting ios/osx application, provided that that is not also prohibited in the various stores in the near future

  * Is the problem being addressed significant enough to warrant a change to Swift?

No. I'll self censor the rest as it is not flatering

The jist is that, as demonstrated by the discussions in the original thread, the proposal as it is worded is incomplete, paving the way to a 0111 scenario if rushed to approval as is.

···

On Jul 17, 2016, at 4:24 AM, L. Mihalkovic <laurent.mihalkovic@gmail.com> wrote:

On Jul 16, 2016, at 7:52 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

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

Feel: not surewhat the feel of swifft is supposed to be anymore
Direction: yes... training wheels all around, limited abilitiy to organize & structure code (other key features missing for that & plenty of real life examples on github to show this is actually the case)

  * If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

The bulk my professional experience has been mostly with asm x86, c, c++, perl, java, scala, tcl/tk, go, xtend, vb, c#, fortran, cobol, javascript and recently TypeScript. None have something equivalent. I recently started toying with kotlin, that looks at inheritence in a similar light, but do not have enough real life experience yet to speak.
As for TypeScript, I only recently started writing large amounts of it professionally, and I am absolutely blown away: it has been the easiest language to learn and become extremely productive with, thanks to the most sound generic type system I have ever used (for bkgrnd, I love and makes very heavy use of the java/c# generics).

  * How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

A lot.

More information about the Swift evolution process is available at

  https://github.com/apple/swift-evolution/blob/master/process.md

Thank you,

-Chris Lattner
Review Manager

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I naturally assumed that "public" and "open" would be two separate
concepts, as it has been expressed that orthogonality* is favored.
But actually reading the proposal, it says:
"open is invalid on declarations that are not also public", which imho
not only is an unnecessary mingling of the two concepts, it also
blocks the option to declare methods that can't be called outside the
framework, which isn't that uncommon in Cocoa (methods like
UIView.drawRect wouldn't show up in autocompletion lists anymore).

One point is to allow the possibility of non-public open methods in the
future, even if we know we don't have the time to design or implement
them today.

···

on Sun Jul 17 2016, Tino Heth <swift-evolution@swift.org> wrote:

The whole proposal is about limitation whose rationale is
incomprehensible for many, but for this "restriction of the
restriction", I can't see any rationale at all.

- Tino

* At class-level, there is afaics no orthogonality planned as well (a
class that is abstract outside its module… might be useful as well)
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Dave

As an alternative to having `open` as a separate access level, we could instead have it merely imply `public`: the canonical form would be `public open`, but source code could just say `open`. Generated interfaces would always say `public open`, so searching for `public` in those would work as you want it to.

I would not support this. Open and public are orthogonal concepts, just like final and public are today.

Just because your internal implementation details involve classes and subclasses, you shouldn't have to expose that to the whole world.

I think it should be an attribute/qualifier on the access level (similar to mutability for properties). You may wish to allow internal subclassing while preventing external subclassing (e.g. The API isn't stable yet, you're thinking of opening it publicly later but you want to refine it through internal usage first).

Or, as I mentioned before, perhaps you are forced to return an "abstract" class because we don't have sealed protocols.

These are all decisions for the API author, and by having the openness scopes to access level we give them ultimate flexibility to annotate which parts of their API can be replaced and by whom.

Karl

···

I disagree that an `open` method overridden from a superclass is implicitly `open`.

As the rationale for the proposal states, overridability is hard to get right, and there is no guarantee that the consumer of an API is going to think about it. The default for override methods should not be `open` or `final`, it should be the internal equivalent.

A coder subclassing a public API, who themselves wants their subclass to be subclassable, should need to restate `open` where appropriate.

I don't think that defaulting to non-open would be a good idea. Like I covered in the proposal, inherited open methods remain open; letting an override implicitly close off an open method would create a pretty unfortunate error-of-omission situation.

We could remove the default here and require the method to be explicitly open/nonopen/final, but then we really do pile up the modifiers:

  public open override func foo()

To me, the fact that it's already marked with "override" suggests the possibility of open-ness enough to remove the need to re-state it. I can see why you might disagree, though.

John.

···

On Jul 17, 2016, at 3:12 PM, Scott James Remnant via swift-evolution <swift-evolution@swift.org> wrote:

This also seems to be a general conflict in that you can always reduce the access, e.g. an API might have a `public open` method, but the subclass should be able to declare that as `override private` and thus the `open` keyword would be invalid in this context.

Scott
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

The second review of "SE-0117: Default classes to be non-subclassable publicly" begins now and runs through July 22. The proposal is available here:

  https://github.com/apple/swift-evolution/blob/master/proposals/0117-non-public-subclassable-by-default.md

  * What is your evaluation of the proposal?

+1, with notes:

1. The interaction of open with the dynamic keyword should be specified. Does "public dynamic" imply “open”? Dynamic provides a level of flexibility beyond mere subclassing, so I believe it should. Dynamic already conflicts with “final”, so there is precedent for this kind of interaction in the language. Note that “public dynamic” implying “open” means that we can’t have public dynamic members in a public class that’s not also open. I think this restriction is reasonable.

Right. I think the right way of thinking about "dynamic" is as a fourth member of this category of polymorphism control modifiers: "dynamic", "open", nonopen (currently unspellable in the proposal), and "final". Depending on where we ultimately go with "dynamic", it's *possible* that we'll want the ability to say "this method can be dynamically changed in-place but not overridden", but... frankly, I doubt we'll do that, and even if we do, it doesn't seem like the right default for "dynamic" alone (possibly "dynamic final"). So I think the answer is that "dynamic" permits overriding.

2. What about @objc methods? The docs say that it makes a name available but doesn’t guarantee dynamic dispatch on its own; so, it looks mostly irrelevant to this proposal.

Correct. @objc just means the method is usable from Objective-C.

3. The problem of code migration should be addressed. For example, we might want the auto-translator to automatically add open to non-final public methods/properties in existing code, to make it less painful to upgrade. People who simply accept the conversion results will get stuck with un-audited open stuff all over their public APIs, which is not ideal. On the other hand, this is no different to how their existing code behaved in Swift 2, so perhaps it is the best choice.

That's a good question. My intuition is that the philosophy of this change suggests that we should leave existing public classes non-open.

4. I don’t have a strong opinion on whether “open" should imply “public". If we accept that “public dynamic” is a stronger promise than “public open", then it would look strange that the former requires public, while the latter doesn’t. On the other hand, “public open” is going to be much more frequently used than “public dynamic”, so arguably it deserves special treatment.

5. I was suprised by the restriction that the superclass of open classes must also be open. But I don’t have a convincing usecase against it, so I guess it’s fine. I like that we have the option to revisit this later.

Right. It's fully source-compatible to allow this later.

John.

···

On Jul 17, 2016, at 5:16 AM, Károly Lőrentey via swift-evolution <swift-evolution@swift.org> wrote:

On 2016-07-16, at 07:52, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

For fun, here are the distinct combinations of access levels and dispatch clauses for members in a "public open" class after this proposal:

public dynamic // plus “public dynamic open” if we keep it separate.
[public] open // assuming “open” implies “public"
public
public final
[internal] dynamic
[internal]
[internal] final
private dynamic
private
private final

  * Is the problem being addressed significant enough to warrant a change to Swift?

Absolutely.

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

Yep.

  * If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

“Don’t use public subclassing" has been my policy for years, but I have not had the pleasure to use a language that helps me enforce this.

  * How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

In-depth study broken across many short sessions.

--
Karoly
@lorentey
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

You know, one thing I haven't seen mentioned is that, just as sealed-by-default preserves the options of library programmers, it also preserves the options of the language itself.

Suppose the people who think this is a huge mistake are correct, and we ultimately conclude that sealed-by-default is a disaster. What can we do about it? Well, we change Swift 3+n to open all classes by default. This would be source- and binary-compatible with all existing code; the only wrinkle is that classes compiled with a sealed-by-default compiler would still be sealed. (And that's not even a problem yet, since stable ABIs are not a thing yet.)

The reverse, however, is *not* true. Going from open-by-default to sealed-by-default is source- and binary-incompatible. If we don't do it now, we may never be able to do it.

That means this is our one chance to try this. The outcome is uncertain; there are good arguments that it will improve things, but there are also good arguments that it will make things worse. But if we're afraid to try this now, we'll never be able to try it again, and we won't know if it would have worked. Whereas if we *do* try it now, we can always roll it back later.

Software quality is one of the biggest problems our profession faces. We handle crushing amounts of complexity, teetering towers of abstraction, intertwined code that's at the ragged edge of our ability to comprehend it. Quite possibly the most urgent need in our industry is tools to help us manage it.

Sealed-by-default might turn out to be a powerful tool for managing complexity, helping us prevent unexpected interactions between the implementation details of separate modules. Or it might not. But we ought to find out. If we always take the conservative option, if we always stick to the tried and true, we will never advance the state of the art, never find solutions to the problems that make "all software sucks" a truism.

We need to be bold and take a chance. If it doesn't work out, we can undo it. But if it does work out, we'll be better for it.

···

On Jul 18, 2016, at 11:04 PM, Gwynne Raskind via swift-evolution <swift-evolution@swift.org> wrote:

Denial of subclassing has always been opt-in in ever other language I’ve used (C++ and Java, to name two, and Objective-C (and older C++) don’t even have that much). Sealing a class against subclassing is one thing, but not providing any kind of escape hatch, any kind of IUnderstandThatSubclassingMayCauseSunsToGoNovaOrGalaxiesToExplode marker, hamstrings all users of the code. Opt-in sealing at least constrains this scenario to places where the framework writer thought it was worth adding the extra protection against horrible horribleness.

--
Brent Royal-Gordon
Architechies

It's hard for me to associate a proposal that is grounded on fear with the word "bold", yet the essence of the message is correct — but Imho it is another "in a perfect world" statement:
In reality, nobody will measure the effect of this change, and those in favor of the proposal might even call the absent of a horrible catastrophe a "proof" for their opinion.
So, what could this catastrophe actually be? Supporters of 0117 educated us that forking is a good thing, and that's about the worst thing I can imagine (exorbitant pessimism left aside)…
We won't have a "free" Swift and a "restricted" Swift to check what people actually prefer, and even if we had, there would be those saying that their opinion is the only truth, no matter what the majority thinks.

The bad effects of the proposal are no obvious danger, like a wild crocodile that threatens you — it is more like a swarm of mosquitos that feasts on your blood and dampens your mood.
I'm am convinced this change will be a source of constant annoyance, but people are very good at accepting constant annoyance (they have even a noticeable track record in accepting things that are much worse than annoyance: It took us hundreds of years to realize that burning old ladies with a talent for leechcraft might not be the smartest idea...).

Despite claims by others, this is not about proofs or facts at all, it is just about attitude, and attitude is hard to change. This article (http://martinfowler.com/bliki/DirectingAttitude.html\) was a big help for me to understand the underlying motives which were absolutely alien to me, and convinced me that there is no merit in discussion anymore:
It's misfortune for our party that those who decide the default belong to the other camp, but that's life, and we have to accept it.

So, regarding the problem of wether subclassing and overriding should be discouraged, we have two contrary positions, and Swift clearly discarded the "enabling attitude"… for those who share this point of view, it is a frustrating decision after a frustrating debate on a frustrating topic, so please be patient with us who walk the narrow path between cynicism and resignation ;-)

Swift is a new language and a projection surface for those taking part in the discussion here, and it is unavoidable that there will be situations that are disappointing for parts of the community*.

- Tino

* although I think that asking an ornithologist for counsel on the choice for the name could have saved us from some irritation... "Cagebird" sounds nice as well, and it is a much better fit for the goals of of 0117, which really don't match with the characteristics of its eponymist ;-)

···

Am 19.07.2016 um 09:43 schrieb Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org>:

We need to be bold and take a chance. If it doesn't work out, we can undo it. But if it does work out, we'll be better for it.

+1 to Brent’s reasoning.

···

On Jul 19, 2016, at 3:43 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

On Jul 18, 2016, at 11:04 PM, Gwynne Raskind via swift-evolution <swift-evolution@swift.org> wrote:

Denial of subclassing has always been opt-in in ever other language I’ve used (C++ and Java, to name two, and Objective-C (and older C++) don’t even have that much). Sealing a class against subclassing is one thing, but not providing any kind of escape hatch, any kind of IUnderstandThatSubclassingMayCauseSunsToGoNovaOrGalaxiesToExplode marker, hamstrings all users of the code. Opt-in sealing at least constrains this scenario to places where the framework writer thought it was worth adding the extra protection against horrible horribleness.

You know, one thing I haven't seen mentioned is that, just as sealed-by-default preserves the options of library programmers, it also preserves the options of the language itself.

Suppose the people who think this is a huge mistake are correct, and we ultimately conclude that sealed-by-default is a disaster. What can we do about it? Well, we change Swift 3+n to open all classes by default. This would be source- and binary-compatible with all existing code; the only wrinkle is that classes compiled with a sealed-by-default compiler would still be sealed. (And that's not even a problem yet, since stable ABIs are not a thing yet.)

The reverse, however, is *not* true. Going from open-by-default to sealed-by-default is source- and binary-incompatible. If we don't do it now, we may never be able to do it.

That means this is our one chance to try this. The outcome is uncertain; there are good arguments that it will improve things, but there are also good arguments that it will make things worse. But if we're afraid to try this now, we'll never be able to try it again, and we won't know if it would have worked. Whereas if we *do* try it now, we can always roll it back later.

Software quality is one of the biggest problems our profession faces. We handle crushing amounts of complexity, teetering towers of abstraction, intertwined code that's at the ragged edge of our ability to comprehend it. Quite possibly the most urgent need in our industry is tools to help us manage it.

Sealed-by-default might turn out to be a powerful tool for managing complexity, helping us prevent unexpected interactions between the implementation details of separate modules. Or it might not. But we ought to find out. If we always take the conservative option, if we always stick to the tried and true, we will never advance the state of the art, never find solutions to the problems that make "all software sucks" a truism.

We need to be bold and take a chance. If it doesn't work out, we can undo it. But if it does work out, we'll be better for it.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

2016/07/19 16:43、Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> のメッセージ:

Denial of subclassing has always been opt-in in ever other language I’ve used (C++ and Java, to name two, and Objective-C (and older C++) don’t even have that much). Sealing a class against subclassing is one thing, but not providing any kind of escape hatch, any kind of IUnderstandThatSubclassingMayCauseSunsToGoNovaOrGalaxiesToExplode marker, hamstrings all users of the code. Opt-in sealing at least constrains this scenario to places where the framework writer thought it was worth adding the extra protection against horrible horribleness.

You know, one thing I haven't seen mentioned is that, just as sealed-by-default preserves the options of library programmers, it also preserves the options of the language itself.

Suppose the people who think this is a huge mistake are correct, and we ultimately conclude that sealed-by-default is a disaster. What can we do about it? Well, we change Swift 3+n to open all classes by default. This would be source- and binary-compatible with all existing code; the only wrinkle is that classes compiled with a sealed-by-default compiler would still be sealed. (And that's not even a problem yet, since stable ABIs are not a thing yet.)

This is exactly my thought as well, if it does end up not optimal it can always be changed back in a subsequent update.

The reverse, however, is *not* true. Going from open-by-default to sealed-by-default is source- and binary-incompatible. If we don't do it now, we may never be able to do it.

That means this is our one chance to try this. The outcome is uncertain; there are good arguments that it will improve things, but there are also good arguments that it will make things worse. But if we're afraid to try this now, we'll never be able to try it again, and we won't know if it would have worked. Whereas if we *do* try it now, we can always roll it back later.

I got the feeling that's why this is being pushed now and not swift 3.1 or 4...

Software quality is one of the biggest problems our profession faces. We handle crushing amounts of complexity, teetering towers of abstraction, intertwined code that's at the ragged edge of our ability to comprehend it. Quite possibly the most urgent need in our industry is tools to help us manage it.

This is implicitly the reason that I changed my +0 to +1, alot of software is crap and it's crap because we don't get a handle on complexity, and this has a potential to reign some things in and bring a little discipline where it's needed.

I was originally very very against this, but as I thought about it I realized my only "real" reason at the end of the day was fear: fear of loosing certain flexibility, fear of loosing a tool I have used in the past, fear of change (again only speaking for myself) ... and really what I'm getting in return for that change though is the potential for some real increase in reliability (and maybe a lot of performance) on all sides.

Things really teeter out of control I think because we can do all this crazy stuff behind the back of everything else and while this gives great flexibility to do some truly remarkable things, it also piles up on top of itself and mucks things up... it works until it doesn't... and while the objc world is much more disciplined than others, my experience in the PHP/JavaScript side of things makes me never want to go back to that place... infinite regresses into over-complexity...

Sealed-by-default might turn out to be a powerful tool for managing complexity, helping us prevent unexpected interactions between the implementation details of separate modules. Or it might not. But we ought to find out. If we always take the conservative option, if we always stick to the tried and true, we will never advance the state of the art, never find solutions to the problems that make "all software sucks" a truism.

Agreed, and I'm ironically reminded of the old days (as a barely conscious human being) where everyone was poopooing objective-c and why don't we just stick to codewarrior and metrowerks and c++... new is bad and what we had is just fine, interface builder is weird, oh and those square brackets what are those etc etc... I'm not saying this is the same thing or that arguments against this proposal are not merited (of course they're merited) but it's a trade off and I think what we would get in return would be huge and potentially more useful in the long run. (wow have i come full circle...)

Maybe we do need to be able to unscrew the bottle and be able to override something forcefully as a last resort and maybe I should have not voted a full +1 because I agree with others that it's an important function... but in any case I think we should take a deep breath and long term think about what is really trying to be accomplished....

We need to be bold and take a chance. If it doesn't work out, we can undo it. But if it does work out, we'll be better for it.

+1000 yes

Andre

···

On Jul 18, 2016, at 11:04 PM, Gwynne Raskind via swift-evolution <swift-evolution@swift.org> wrote:

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

+1 I'm sold by Brent's reasoning that sealed is the only way to keep options open, both for any given library and for the whole Swift language. I've stayed quiet until now because while philosophically inclined to final by default I was concerned about potential complexity and confusion.

I haven't read everything on the mailing list but I've read several blog posts on both sides.

In terms of the necessity of subclassing it feels to me that subclassing where not designed for it is a similar in principle to using private APIs which may at times be the only way to achieve certain things but at least on iOS the App Store policies prevent that.

I don't have very strong views about the syntax I'm afraid but if this is something that could be reversed there should be an explicit version of the default sealed case (like internal is with for access controls).

Joseph

···

On Jul 19, 2016, at 8:43 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

On Jul 18, 2016, at 11:04 PM, Gwynne Raskind via swift-evolution <swift-evolution@swift.org> wrote:

Denial of subclassing has always been opt-in in ever other language I’ve used (C++ and Java, to name two, and Objective-C (and older C++) don’t even have that much). Sealing a class against subclassing is one thing, but not providing any kind of escape hatch, any kind of IUnderstandThatSubclassingMayCauseSunsToGoNovaOrGalaxiesToExplode marker, hamstrings all users of the code. Opt-in sealing at least constrains this scenario to places where the framework writer thought it was worth adding the extra protection against horrible horribleness.

You know, one thing I haven't seen mentioned is that, just as sealed-by-default preserves the options of library programmers, it also preserves the options of the language itself.

Suppose the people who think this is a huge mistake are correct, and we ultimately conclude that sealed-by-default is a disaster. What can we do about it? Well, we change Swift 3+n to open all classes by default. This would be source- and binary-compatible with all existing code; the only wrinkle is that classes compiled with a sealed-by-default compiler would still be sealed. (And that's not even a problem yet, since stable ABIs are not a thing yet.)

The reverse, however, is *not* true. Going from open-by-default to sealed-by-default is source- and binary-incompatible. If we don't do it now, we may never be able to do it.

That means this is our one chance to try this. The outcome is uncertain; there are good arguments that it will improve things, but there are also good arguments that it will make things worse. But if we're afraid to try this now, we'll never be able to try it again, and we won't know if it would have worked. Whereas if we *do* try it now, we can always roll it back later.

Software quality is one of the biggest problems our profession faces. We handle crushing amounts of complexity, teetering towers of abstraction, intertwined code that's at the ragged edge of our ability to comprehend it. Quite possibly the most urgent need in our industry is tools to help us manage it.

Sealed-by-default might turn out to be a powerful tool for managing complexity, helping us prevent unexpected interactions between the implementation details of separate modules. Or it might not. But we ought to find out. If we always take the conservative option, if we always stick to the tried and true, we will never advance the state of the art, never find solutions to the problems that make "all software sucks" a truism.

We need to be bold and take a chance. If it doesn't work out, we can undo it. But if it does work out, we'll be better for it.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I agree with Kevin Ballard on being open by default for methods/ properties http://article.gmane.org/gmane.comp.lang.swift.evolution/23467/

If we are open by default for methods/properties then we could simplify things by just using final for methods that need to be sealed; I don’t see the need to have sealed methods/properties outside of the module ONLY.

The proposal (and additional comments) explain this point fairly well. Usually, it makes sense to be overridable only for few select members — and compiler can’t easily figure out which entry points these are as the API invariants are not explicit. By making members sealed by default, the API contracts are made more clear. Second (and a very important reason) is performance — if everything is open by default, the compiler can’t devirtualize property accessors even though it would be appropriate most of the time. The compiler can infer the ‚final‘ status of definitions within a module easily and optimise accordingly, which wot work if these definitions can be overridden externally. To put it differently, its much easier for the compiler to determine what can be safely considered final than what can be safely considered sealed. The design choices in the proposal follow naturally from these considerations.

The compiler is welcome to optimize my sealed classes but once I slap `open` on the class, I am telling the compiler that I am not interested in the automatic optimizations imo.

The final keyword still has its use, although I think its utility will be somewhat diminished after this proposal. You can still use it for things that can’t be overridden internally. Like classes that are intended only to be used as ‚structs with reference semantics’.

struct with reference semantics is what sealed classes are, but once I make the class open, i’d like for it to act like a regular subclassable class.

···

On Jul 16, 2016, at 9:18 AM, Taras Zakharko <taras.zakharko@uzh.ch> wrote:

On 16 Jul 2016, at 18:05, Jose Cheyo Jimenez via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

— T

Is there a summary somewhere of the motivation for allowing methods to be declared non-overridable within open classes?

I’m not asking about any particular syntax or default, just why you'd want this facility at all. The proposal doesn’t mention this, and the discussion of the initial version never really seemed to reach the issue, either.

I can see that there’s a potential for static dispatch on non-overridable methods when called from outside the module. But presumably there’s an architectural argument in favor of this restriction as well.

Garth

Are they? Given that "open" *means* "subclassable/overridable in public scope", what would it mean for something to be open, but not public? `final` *is* orthogonal, but I'm not sure `open` is.

···

On Jul 17, 2016, at 7:29 AM, Karl Wagner <razielim@gmail.com> wrote:

Open and public are orthogonal concepts, just like final and public are today.

--
Brent Royal-Gordon
Architechies

I too would be interested in this info. Brent's numbers look daunting
indeed (nearly 2000 annotations for methods and properties in
corelibs-foundation alone). What use cases are supported by
sealed-but-not-final public methods in open classes?

···

On Sun, Jul 17, 2016 at 2:14 PM, Garth Snyder via swift-evolution < swift-evolution@swift.org> wrote:

Is there a summary somewhere of the motivation for allowing methods to be
declared non-overridable within open classes?

I’m not asking about any particular syntax or default, just why you'd want
this facility at all. The proposal doesn’t mention this, and the discussion
of the initial version never really seemed to reach the issue, either.

I can see that there’s a potential for static dispatch on non-overridable
methods when called from outside the module. But presumably there’s an
architectural argument in favor of this restriction as well.

Garth

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Regards
(From mobile)

Is there a summary somewhere of the motivation for allowing methods to be declared non-overridable within open classes?

I’m not asking about any particular syntax or default, just why you'd want this facility at all. The proposal doesn’t mention this, and the discussion of the initial version never really seemed to reach the issue, either.

I can see that there’s a potential for static dispatch on non-overridable methods when called from outside the module. But presumably there’s an architectural argument in favor of this restriction as well.

Because 1) someone woke up one morning and thought it would be great 2) it goes into the direction of making swift a language for non programmers 3) the core team wants it

···

On Jul 17, 2016, at 9:14 PM, Garth Snyder via swift-evolution <swift-evolution@swift.org> wrote:

Garth

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I think that this explicitness is more Swifty.

First consider why `open` is a bad inherited default:

  public class Superclass {
    public func foo() { }
  }

  class Subclass : Superclass {
    override func foo() { }
  }

Subclass is `internal` not `public`, likewise Subclass.foo is `internal` and not `public`. If the default was that these became `open`, the default would be compiler errors at every definition (and compiler errors for everything that was defined in the superclass that you haven’t overridden) because Subclass cannot be `open` and `internal`, and Subclass.foo cannot be `open` and `internal`.

And requiring that your derivation from a public API be also public seems exactly opposite to the intent of “apply thought before making things public,” and very much against “apply even more thought before making public things open."

To make anything public, even a subclass, you have to be explicit in Swift already not just at the class level:

  public class Superclass {
    public func foo() { }
  }

  public class Subclass : Superclass {
    override func foo() { } // Error: Overriding instance method must be accessible as the declaration it overrides.
  }

But the function level too:

  public class Superclass {
    public func foo() { }
  }

  public class Subclass : Superclass {
    override public func foo() { }
  }

So I really don’t agree that `open` suggests anything, in fact I think consistently in Swift restating things is the norm.

Scott

···

On Jul 18, 2016, at 10:12 AM, John McCall <rjmccall@apple.com> wrote:

On Jul 17, 2016, at 3:12 PM, Scott James Remnant via swift-evolution <swift-evolution@swift.org> wrote:
I disagree that an `open` method overridden from a superclass is implicitly `open`.

As the rationale for the proposal states, overridability is hard to get right, and there is no guarantee that the consumer of an API is going to think about it. The default for override methods should not be `open` or `final`, it should be the internal equivalent.

A coder subclassing a public API, who themselves wants their subclass to be subclassable, should need to restate `open` where appropriate.

I don't think that defaulting to non-open would be a good idea. Like I covered in the proposal, inherited open methods remain open; letting an override implicitly close off an open method would create a pretty unfortunate error-of-omission situation.

We could remove the default here and require the method to be explicitly open/nonopen/final, but then we really do pile up the modifiers:

public open override func foo()

To me, the fact that it's already marked with "override" suggests the possibility of open-ness enough to remove the need to re-state it. I can see why you might disagree, though.

Then we would need another keyword to close the method again should we
need/want.

   public sealed override func foo()

I don't see any association between override and open/sealed as they
relate to two different aspects of class inheritance. One declares the
method is overriding a superclass method; the other that this method
can(not) be further overriden. With inherited openness, it should be
possible to revert it and defaulting to inherited openness will demand
the introduction of another keword (sealed/closed/nonopen).

It would be simpler to have one global default and one keyword only.
Two keywords add to complexity to learn the language.

L

···

On 18 July 2016 at 14:12, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Jul 17, 2016, at 3:12 PM, Scott James Remnant via swift-evolution <swift-evolution@swift.org> wrote:
I disagree that an `open` method overridden from a superclass is implicitly `open`.

As the rationale for the proposal states, overridability is hard to get right, and there is no guarantee that the consumer of an API is going to think about it. The default for override methods should not be `open` or `final`, it should be the internal equivalent.

A coder subclassing a public API, who themselves wants their subclass to be subclassable, should need to restate `open` where appropriate.

I don't think that defaulting to non-open would be a good idea. Like I covered in the proposal, inherited open methods remain open; letting an override implicitly close off an open method would create a pretty unfortunate error-of-omission situation.

We could remove the default here and require the method to be explicitly open/nonopen/final, but then we really do pile up the modifiers:

  public open override func foo()

To me, the fact that it's already marked with "override" suggests the possibility of open-ness enough to remove the need to re-state it. I can see why you might disagree, though.

John.

This also seems to be a general conflict in that you can always reduce the access, e.g. an API might have a `public open` method, but the subclass should be able to declare that as `override private` and thus the `open` keyword would be invalid in this context.

Scott
_______________________________________________
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

Regards
(From mobile)

I disagree that an `open` method overridden from a superclass is implicitly `open`.

As the rationale for the proposal states, overridability is hard to get right, and there is no guarantee that the consumer of an API is going to think about it. The default for override methods should not be `open` or `final`, it should be the internal equivalent.

A coder subclassing a public API, who themselves wants their subclass to be subclassable, should need to restate `open` where appropriate.

I don't think that defaulting to non-open would be a good idea. Like I covered in the proposal, inherited open methods remain open; letting an override implicitly close off an open method would create a pretty unfortunate error-of-omission situation.

We could remove the default here and require the method to be explicitly open/nonopen/final, but then we really do pile up the modifiers:

public open override func foo()

To me, the fact that it's already marked with "override" suggests the possibility of open-ness enough to remove the need to re-state it. I can see why you might disagree, though.

the fact that someone thought that something could be extended does not imply that the one who extended it also carefully planed for her own code to be extensible... and even if one particular method A which was declared extensible has not been altered directly in a subclass, through extending others that are related and not having planned carefully the interplay, method A may have now been rendered unfit for further extension.

So simply as a matter of following the logic of the proposal, every subsequent extension of something explicitely marked as open for subclassing should defacto be placed back into the default non-subclassable state, forcing the author to have to explicitely validate the new set of relationships existing between the methods in the subclass. Otherwise the logic does not hold, and the original proposal does not hold water: that which cannot be assumed as safe on level 0, cannot be suddenly assumed safe at level 1 of subclassing, because the outer API surface of level-n subclasing forms no more implicite guaranty of soundness than existed at level n-1. The proposal is all about the fact that it is the developer who MUST PROVIDE the soundness guaranty.

···

On Jul 18, 2016, at 7:12 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Jul 17, 2016, at 3:12 PM, Scott James Remnant via swift-evolution <swift-evolution@swift.org> wrote:

John.

This also seems to be a general conflict in that you can always reduce the access, e.g. an API might have a `public open` method, but the subclass should be able to declare that as `override private` and thus the `open` keyword would be invalid in this context.

Scott
_______________________________________________
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

Agreed, and I'm ironically reminded of the old days (as a barely conscious human being) where everyone was poopooing objective-c [...], interface builder is weird, oh and those square brackets what are those etc etc...

Ironically we are back to the same dismissive attitude when taking about Objective-C now it seems lol, history does likes cycles sometimes ;).

I am in favour of Swift taking chances, but throwing away with disgust everything which is not the brand new hope does a major disservice to the achievements and productivity the previous instruments bring and the lessons they teach.

···

Sent from my iPhone

On 19 Jul 2016, at 15:36, Andre via swift-evolution <swift-evolution@swift.org> wrote: