[Proposal] Sealed classes by default

Regards
LM
(From mobile)

-1 for the fact that if all devs can write working code, fewer can do it in a clear structured fashion that is well designed for extensibility.

This sounds more like an argument for having sealed classes than not. As the proposal points out in the motivation, if the base class is not designed with subclassing in mind then overriding methods can result in unintended behavior (e.g. crashing, or other bugs).

The pb i am referencing is devs who think their code is designed for extension but ends up being awkward or incompletely so. In my exp this is true of lots of (most) libs, including prominent projects. I got this sense over the years that a lot if newb designers want to play gods by showing how well they can juggle the different levels of privacy/locking in a language to create great extensible codebases.. and after getting burned a few times by their inability to think holistically about all possible codepaths, they become more humble and write more straightforward code that in the end becomes more extensible.

Crashing because of me deciding to extend something not ready for should remain my responsibility, because in the end this is no different than my own code crashing because of my bugs. I think it should be everyone's responsibility to make sure we pay attention when drinking hot coffee, not the responsibility of mcDonald to write in caps on their cups that hot liquids tend to cause burns.

···

On Jun 28, 2016, at 4:52 PM, Mark Lacey <mark.lacey@apple.com> wrote:

On Jun 27, 2016, at 9:10 PM, L. Mihalkovic via swift-evolution <swift-evolution@swift.org> wrote:

Mark

A couple months ago I even ran into difficulties when trying to extend AlamoFire because some things had not been designed as cleanly as they could have been to make extending it easy. So if the default is now that everything becomes non-extensible but default, it is going to complicate (and partially defeat the purpose of) reusing libraries.
Regards
(From mobile)

On Jun 28, 2016, at 2:11 AM, Michael Ilseman via swift-evolution <swift-evolution@swift.org> wrote:

I was also referring to how we present Objective-C classes in Swift. That is, if a Swift user tries to subclass an Objective-C-imported class, then we’d take into account sealed-ness in order to issue an error/warning, etc. If you are also proposing a Clang attribute for this, e.g. ‘swift_sealed’, to import as sealed (meaning issue an error if Swift users try to subclass it), then that should be spelled out as well. I don’t have an opinion on whether this is a good idea yet, just pointing out some more directions to explore. In general it feels like your proposal could use more fleshing out.

On Jun 27, 2016, at 5:08 PM, Javier Soto <javier.api@gmail.com> wrote:

That is a very good point, it should be explicitly mentioned in the proposal. My thought would be that since in the Obj-C runtime it's not possible to guarantee a class won't have subclasses, or that a method is not overriden, Obj-C classes would be imported as open.

On the Swift side, I think today it's possible to declare a "public final @objc class", but you can still inherit from it from Obj-C, right? My hunch would be that that should be disallowed, but perhaps there's a reason why it's allowed today.
On Mon, Jun 27, 2016 at 4:25 PM Michael Ilseman <milseman@apple.com> wrote:

Could you elaborate on how we should treat classes imported from Objective-C or CF-style C? That is, do we always annotate them as being “open” because those paradigms permit subclassing anywhere, or do you propose some kind of recommended “sealed” audit, or what?

On Jun 27, 2016, at 3:40 PM, Javier Soto via swift-evolution <swift-evolution@swift.org> wrote:

Hello!

I sent this as a PR on the swift-evolution repo, but we never had any discussion about it on-list, besides a long time ago. Here's the first draft of the proposal:

Sealed classes by default
Introduction

Introduce a new sealed class modifier that makes classes and methods final outside of the module they're declared in, but non-final within the module.

Motivation

It is not uncommon to have a need for a reference type without needing inheritance. Classes must be intentionally designed to be subclassable, carefully deciding which methods are the override entry-points such that the the behavior remains correct and subclasses respect the Liskov substitution principle.
Defaulting to non-final allows the author of a class to accidentally leave the visible methods open for overrides, even if they didn't carefully consider this possibility.
Requiring that the author of a class mark a class as open is akin to requiring symbols to be explicitly public: it ensures that a conscious decision is made regarding whether the ability to subclass a class is part of the API.
Proposed solution

New sealed (actual name pending bike-shedding) class modifier for classes and methods which marks them as only overridable within the module they're declared in.
sealed becomes the default for classes and methods.
New open (actual name pending bike-shedding) class modifier to explicitly mark a class or a method as overridable.
Detailed design

Code Examples:

/// ModuleA:

/// This class is `sealed` by default.
/// This is equivalent to `sealed class SealedParentClass`
class SealedParentClass {
    /// This method is `sealed` by default`.
    func foo()

    /// This raises a compilation error: a method can't have a "subclassability"
    /// level higher than that of its class.
    open func bar()

    /// The behavior of `final` methods remains unchanged.
    final func baz()
}

open class OpenParentClass {
    /// This method is `sealed` by default`.
    func foo()

    /// Overridable methods in an `open` class must be explicitly marked as `open`.
    open func bar()

    /// The behavior of a `final` method remains unchanged.
    final func baz()
}

/// The behavior of `final` classes remains unchanged.
final class FinalClass { }
/// ModuleB:

import ModuleA

/// This raises a compilation error: ParentClass is effectively `final` from
/// this module's point of view.
class SubclassA : SealedParentClass { }

/// This is allowed since `OpenParentClass` has been marked explicitly `open`
class SubclassB : OpenParentClass {
    /// This raises a compilation error: `OpenParentClass.foo` is
    /// effectively `final` outside of `ModuleA`.
    override func foo() { }

    /// This is allowed since `OpenParentClass.bar` is explicitly `open`.
    override func bar() { }
}
Impact on existing code

This would be a backwards-breaking change for all classes and methods that are public and non-final, which code outside of their module has overriden. Those classes/methods would fail to compile. Their superclass would need to be changed to open.
Alternatives considered

Defaulting to final instead: This would be comparable to Swift defaulting to private, as opposed to internal. Just like internal is a better trade-off, sealed by default also makes sure that getting started with Swift, writing code within a module, doesn't require a lot of boilerplate, and fighting against the compiler.
--
Javier Soto

_______________________________________________
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

Sealing classes by default is a terrible idea IMHO. Fortunately, my faith in the Swift core team is strong enough so that I cannot believe that this has a chance of ever being implemented at all :)

Why do I think it's terrible? I do subclass classes even when they say that you shouldn't do it. I even monkey-patched a few classes in the past. Why? Not because I prefer hacking over clean coding, but to get the job done. Every few months or so I encounter a situation where such hacking attempts are the only feasible way to make something work. Or I use them during research activities or unofficial "feasibility studies". (If that's not the case for you, then maybe you are working in a different job than I. Monkey patching is rarely necessary if you make iPhone apps.) These are situations where everyone else just says "that's not possible". Yes, you can make that USB driver class stop spamming the console; yes, you can stop that library from crashing randomly.

There is so much more to say on this topic. Sealing classes is also bad because it prevents forms of experimental coding. It doesn't solve a real problem. How often have I seen bugs where someone subclassed a class that shouldn't be subclassed? That's so rare. But if all classes are sealed by default this will lead to far worse problems. When a developer subclasses a class, he usually has a reason. There already is a `final` keyword in Swift, and a dev really thinks that a class shouldn't be subclass-able, he can use it already. And if I subclass it from Objective-C anyways, then maybe I know what I'm doing?

And I'm not buying this "performance" argument. If you want better performance, write the hot functions in C or maybe even in assembler. The dynamic dispatch overhead is not the feature that makes programs bad or slow. It's quadratic algorithms (e.g. unnecessary nested loops), calling functions multiple times (e.g. if(a.foo.bar(x[2]) == "joo" || a.foo.bar(x[2]) == "fooo" || a.foo.bar(x[2]) == nil) { ... }), or just overly complex code: all of them have more impact than dynamic dispatch. Even worse for performance is unnecessary IO or using graphics APIs inefficiently. A good profiler can help a lot with these issues.

Swift should be designed for the real world, not for an ideal world that does not exist and that will never exist.

-Michael

···

Am 28.06.2016 um 15:09 schrieb L. Mihalkovic via swift-evolution <swift-evolution@swift.org>:

Regards
LM
(From mobile)

On Jun 28, 2016, at 1:57 PM, Alejandro Martinez via swift-evolution <swift-evolution@swift.org> wrote:

Anton Zhilin: That is one of the points if I’m not mistaken. Sealed
means that with whole-module-optimization the compiler can optimise
more things as it can treat it as final for other modules.

L. Mihalkovic: Could you give an example of what exactly do you mean?
I know one of the reasons behind the proposal is to actually improve
those situations by forcing us to think more on customisation when
designing APIs.

In many situation it has been my experience that libraries can be extended DESPITE their authors, rather than only thanks to the skills the authors have shown in planning for the future. It is what happened to me with AlamoFire, where i was able to extend it because some cracks existed which let me do something the designers did not think about (to me it was a lack of imagination to not have anticipated what i wanted to do).

So if this can happen with a lib made by very experienced/talented developers, then imagine what happens with far less skilled developers.. it will mean having to copy code in order extend. It may sound pessimistic, but if u had seen as much bad code as i have seen, you might understand the view i am sharing.

What's worse is that objc is not particularly conducive to good software architecture (it is a bit like perl and javascript where anything can be touched from anywhere, and has a limited set of constructs compared to c++, scala, java, c#, swift). So i do not believe that it has prepared objc devs to suddenly become great code designers with a language that has multiples levels of scoping/nesting (i would not use most of the swift libs i have seen on github to teach software design).

Hence my conclusion that defaulting to sealed may be giving too much credit to the code that is currently available for reuse.

On Tue, Jun 28, 2016 at 12:44 PM, Anton Zhilin via swift-evolution >> <swift-evolution@swift.org> wrote:

Does `sealed` allow for any optimizations? Maybe somehow devirtualizing
method calls?

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

--
Alejandro Martinez
http://alejandromp.com
_______________________________________________
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

Do you mean `public(unsealed)`? Because `internal(unsealed)` doesn't really make sense. `internal` declarations are always sealed.

Right.

If "sealed" is the default behavior for public classes and methods — and I don't think the modifier is worth adding unless it's the default — then we need a way of "unsealing" classes and methods that's fairly pithy. I don't think a parenthesized spelling is good enough for that. And we should try to make the positive form ("can be overridden") shorter than the negative ("cannot be overridden"), because the latter will not usually be written.

To me, the ideal spelling would be usable in place of "public". If it does have to be stacked with "public", then I think it ought to be pretty short.

"communal"? :)

"open" doesn't carry quite the right meaning, and it would need to be paired with "public", I think.

John.

···

On Jun 29, 2016, at 11:16 AM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

-Michael

Am 29.06.2016 um 20:11 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

Do we really need a new keyword? Since we already have syntax like `internal(set)` couldn't we do `internal(unsealed)`, etc.

On Wed, Jun 29, 2016 at 12:21 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 29, 2016, at 12:15 PM, Michael Peternell <michael.peternell@gmx.at> wrote:

Am 29.06.2016 um 15:54 schrieb David Sweeris via swift-evolution <swift-evolution@swift.org>:

+1 for the concept of a "sealed” class.
-1 for making it default.

Aren't sealed classes already implemented? I think the keyword is `final`..
So there is nothing left to do :)

No, `final` doesn’t allow for any subclassing, but `sealed` allows for subclassing within your module (where you can presumably write more efficient code based on knowledge of each subclass).

- Dave Sweeris
_______________________________________________
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

I actually thought about something like 'public(final)' as it may make
it clearer the intention to the class (and no new keywords were
introduced).

Also I think we should draw a guideline for such naming because there
are always so many suggestions. Having a guideline would reduce our
efforts in choosing names.

L

···

On 29 June 2016 at 15:16, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

Do you mean `public(unsealed)`? Because `internal(unsealed)` doesn't really make sense. `internal` declarations are always sealed.

-Michael

Am 29.06.2016 um 20:11 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

Do we really need a new keyword? Since we already have syntax like `internal(set)` couldn't we do `internal(unsealed)`, etc.

On Wed, Jun 29, 2016 at 12:21 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:
> On Jun 29, 2016, at 12:15 PM, Michael Peternell <michael.peternell@gmx.at> wrote:
>
>
>> Am 29.06.2016 um 15:54 schrieb David Sweeris via swift-evolution <swift-evolution@swift.org>:
>>
>> +1 for the concept of a "sealed” class.
>> -1 for making it default.
>
> Aren't sealed classes already implemented? I think the keyword is `final`..
> So there is nothing left to do :)

No, `final` doesn’t allow for any subclassing, but `sealed` allows for subclassing within your module (where you can presumably write more efficient code based on knowledge of each subclass).

- Dave Sweeris
_______________________________________________
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

How about `public(extensible)` ?

···

On 29.06.2016 21:32, John McCall via swift-evolution wrote:

On Jun 29, 2016, at 11:16 AM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:
Do you mean `public(unsealed)`? Because `internal(unsealed)` doesn't really make sense. `internal` declarations are always sealed.

Right.

If "sealed" is the default behavior for public classes and methods — and I don't think the modifier is worth adding unless it's the default — then we need a way of "unsealing" classes and methods that's fairly pithy. I don't think a parenthesized spelling is good enough for that. And we should try to make the positive form ("can be overridden") shorter than the negative ("cannot be overridden"), because the latter will not usually be written.

To me, the ideal spelling would be usable in place of "public". If it does have to be stacked with "public", then I think it ought to be pretty short.

"communal"? :)

"open" doesn't carry quite the right meaning, and it would need to be paired with "public", I think.

John.

-Michael

Am 29.06.2016 um 20:11 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

Do we really need a new keyword? Since we already have syntax like `internal(set)` couldn't we do `internal(unsealed)`, etc.

On Wed, Jun 29, 2016 at 12:21 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 29, 2016, at 12:15 PM, Michael Peternell <michael.peternell@gmx.at> wrote:

Am 29.06.2016 um 15:54 schrieb David Sweeris via swift-evolution <swift-evolution@swift.org>:

+1 for the concept of a "sealed” class.
-1 for making it default.

Aren't sealed classes already implemented? I think the keyword is `final`..
So there is nothing left to do :)

No, `final` doesn’t allow for any subclassing, but `sealed` allows for subclassing within your module (where you can presumably write more efficient code based on knowledge of each subclass).

- Dave Sweeris
_______________________________________________
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

I actually thought about something like 'public(final)' as it may make
it clearer the intention to the class (and no new keywords were
introduced).

I also though about public(final), but it may be confused with "public final" which can be used to defined a class final even in the module scope.

···

Le 29 juin 2016 à 21:41, Leonardo Pessoa via swift-evolution <swift-evolution@swift.org> a écrit :

Also I think we should draw a guideline for such naming because there
are always so many suggestions. Having a guideline would reduce our
efforts in choosing names.

L

On 29 June 2016 at 15:16, Michael Peternell via swift-evolution > <swift-evolution@swift.org> wrote:

Do you mean `public(unsealed)`? Because `internal(unsealed)` doesn't really make sense. `internal` declarations are always sealed.

-Michael

Am 29.06.2016 um 20:11 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

Do we really need a new keyword? Since we already have syntax like `internal(set)` couldn't we do `internal(unsealed)`, etc.

On Wed, Jun 29, 2016 at 12:21 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 29, 2016, at 12:15 PM, Michael Peternell <michael.peternell@gmx.at> wrote:

Am 29.06.2016 um 15:54 schrieb David Sweeris via swift-evolution <swift-evolution@swift.org>:

+1 for the concept of a "sealed” class.
-1 for making it default.

Aren't sealed classes already implemented? I think the keyword is `final`..
So there is nothing left to do :)

No, `final` doesn’t allow for any subclassing, but `sealed` allows for subclassing within your module (where you can presumably write more efficient code based on knowledge of each subclass).

- Dave Sweeris
_______________________________________________
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

Sure, I understand that, and I don’t mean to trivialize that concern. I’m just pointing out that “code…that is [not] well designed for extensibility”, might not work very well if you start using extension points that weren’t well thought through.

If you are designing for extensibility you’ll be carefully thinking about what should and should not be final both within and outside of your module. Not doing so can result in bugs. This proposal introduces the ability to allow extension within the module but restrict it outside the module, and defaults to not allowing extension beyond the module.

You can argue both ways which default would be better, and I suspect people who mostly write libraries might opt for sealed-by-default, and people who mostly consume libraries might opt for open-by-default. My point is that open-by-default isn’t “better” because it allows you to potentially work around a problem in a base class, because by working around that problem by overriding a method that wasn’t designed to be overridden you don’t know how many other new problems you might be introducing (now or in the future if the implementation of the base class changes).

Mark

···

On Jun 28, 2016, at 7:55 AM, Sean Heber <sean@fifthace.com> wrote:

On Jun 28, 2016, at 9:52 AM, Mark Lacey via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 27, 2016, at 9:10 PM, L. Mihalkovic via swift-evolution <swift-evolution@swift.org> wrote:

-1 for the fact that if all devs can write working code, fewer can do it in a clear structured fashion that is well designed for extensibility.

This sounds more like an argument for having sealed classes than not. As the proposal points out in the motivation, if the base class is not designed with subclassing in mind then overriding methods can result in unintended behavior (e.g. crashing, or other bugs).

But I think the counter argument is, what if you need to fix or workaround unintended behavior of the class you’re trying to use?

-1 for the fact that if all devs can write working code, fewer can do it in a clear structured fashion that is well designed for extensibility.

This sounds more like an argument for having sealed classes than not. As the proposal points out in the motivation, if the base class is not designed with subclassing in mind then overriding methods can result in unintended behavior (e.g. crashing, or other bugs).

But I think the counter argument is, what if you need to fix or workaround unintended behavior of the class you’re trying to use?

Sure, I understand that, and I don’t mean to trivialize that concern. I’m just pointing out that “code…that is [not] well designed for extensibility”, might not work very well if you start using extension points that weren’t well thought through.

If you are designing for extensibility you’ll be carefully thinking about what should and should not be final both within and outside of your module. Not doing so can result in bugs. This proposal introduces the ability to allow extension within the module but restrict it outside the module, and defaults to not allowing extension beyond the module.

You can argue both ways which default would be better, and I suspect people who mostly write libraries might opt for sealed-by-default, and people who mostly consume libraries might opt for open-by-default. My point is that open-by-default isn’t “better” because it allows you to potentially work around a problem in a base class, because by working around that problem by overriding a method that wasn’t designed to be overridden you don’t know how many other new problems you might be introducing (now or in the future if the implementation of the base class changes).

I think a good argument for sealed by default is that if we introduce `sealed` responsible library authors will already be marking all classes not intended for external subclassing as either `sealed` or `final` anyway. The intended (and hopefully actual) public API will be identical regardless of the default. Making it the default avoids a lot of boilerplate keywords and makes ensure the API contract is stated more explicitly.

The only case where the default should make a difference is when a library is written without consideration of subclasses. As you point out, in that case it is a really bad idea to attempt to work around a bug with a subclass.

···

On Jun 28, 2016, at 10:17 AM, Mark Lacey via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 28, 2016, at 7:55 AM, Sean Heber <sean@fifthace.com> wrote:

On Jun 28, 2016, at 9:52 AM, Mark Lacey via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 27, 2016, at 9:10 PM, L. Mihalkovic via swift-evolution <swift-evolution@swift.org> wrote:

Mark

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

Sealing classes by default is a terrible idea IMHO. Fortunately, my faith in the Swift core team is strong enough so that I cannot believe that this has a chance of ever being implemented at all :)

Why do I think it's terrible? I do subclass classes even when they say that you shouldn't do it. I even monkey-patched a few classes in the past. Why? Not because I prefer hacking over clean coding, but to get the job done. Every few months or so I encounter a situation where such hacking attempts are the only feasible way to make something work. Or I use them during research activities or unofficial "feasibility studies". (If that's not the case for you, then maybe you are working in a different job than I. Monkey patching is rarely necessary if you make iPhone apps.) These are situations where everyone else just says "that's not possible". Yes, you can make that USB driver class stop spamming the console; yes, you can stop that library from crashing randomly.

There is so much more to say on this topic. Sealing classes is also bad because it prevents forms of experimental coding. It doesn't solve a real problem. How often have I seen bugs where someone subclassed a class that shouldn't be subclassed? That's so rare. But if all classes are sealed by default this will lead to far worse problems. When a developer subclasses a class, he usually has a reason. There already is a `final` keyword in Swift, and a dev really thinks that a class shouldn't be subclass-able, he can use it already. And if I subclass it from Objective-C anyways, then maybe I know what I'm doing?

And I'm not buying this "performance" argument. If you want better performance, write the hot functions in C or maybe even in assembler. The dynamic dispatch overhead is not the feature that makes programs bad or slow. It's quadratic algorithms (e.g. unnecessary nested loops), calling functions multiple times (e.g. if(a.foo.bar(x[2]) == "joo" || a.foo.bar(x[2]) == "fooo" || a.foo.bar(x[2]) == nil) { ... }), or just overly complex code: all of them have more impact than dynamic dispatch. Even worse for performance is unnecessary IO or using graphics APIs inefficiently. A good profiler can help a lot with these issues.

Swift should be designed for the real world, not for an ideal world that does not exist and that will never exist.

The design intent of much of Swift is to allow "free" coding within a module/file/type while encouraging programmers to think more carefully about their public interfaces. Module interfaces are the most serious and permanent of these interfaces. It's in keeping with that for declarations to make only minimal public guarantees and require the programmer to be more explicit about the things they want to allow.

Your arguments about patchability and performance could be applied to every feature in the language. They are essentially arguments for a fully-dynamic environment. There's no reason to single out subclassing; for everything you can imagine, one programmer's caution will be another's paternalism. You're just making the argument here because you're used to a particular way of patching Objective-C code, one which will work regardless of this language decision; but most of the old ObjC techniques (e.g. accessing ivars reflectively) already won't work on Swift code without unsafe operations, and subclassing is a very tiny part of that problem.

And no, we do not and will not accept that performance-sensitive code can only possibly be written in C or assembly, or that algorithmic performance is the only thing worth worrying about, even for the language implementation.

John.

···

On Jun 28, 2016, at 12:39 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

-Michael

Am 28.06.2016 um 15:09 schrieb L. Mihalkovic via swift-evolution <swift-evolution@swift.org>:

Regards
LM
(From mobile)

On Jun 28, 2016, at 1:57 PM, Alejandro Martinez via swift-evolution <swift-evolution@swift.org> wrote:

Anton Zhilin: That is one of the points if I’m not mistaken. Sealed
means that with whole-module-optimization the compiler can optimise
more things as it can treat it as final for other modules.

L. Mihalkovic: Could you give an example of what exactly do you mean?
I know one of the reasons behind the proposal is to actually improve
those situations by forcing us to think more on customisation when
designing APIs.

In many situation it has been my experience that libraries can be extended DESPITE their authors, rather than only thanks to the skills the authors have shown in planning for the future. It is what happened to me with AlamoFire, where i was able to extend it because some cracks existed which let me do something the designers did not think about (to me it was a lack of imagination to not have anticipated what i wanted to do).

So if this can happen with a lib made by very experienced/talented developers, then imagine what happens with far less skilled developers.. it will mean having to copy code in order extend. It may sound pessimistic, but if u had seen as much bad code as i have seen, you might understand the view i am sharing.

What's worse is that objc is not particularly conducive to good software architecture (it is a bit like perl and javascript where anything can be touched from anywhere, and has a limited set of constructs compared to c++, scala, java, c#, swift). So i do not believe that it has prepared objc devs to suddenly become great code designers with a language that has multiples levels of scoping/nesting (i would not use most of the swift libs i have seen on github to teach software design).

Hence my conclusion that defaulting to sealed may be giving too much credit to the code that is currently available for reuse.

On Tue, Jun 28, 2016 at 12:44 PM, Anton Zhilin via swift-evolution >>> <swift-evolution@swift.org> wrote:

Does `sealed` allow for any optimizations? Maybe somehow devirtualizing
method calls?

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

--
Alejandro Martinez
http://alejandromp.com
_______________________________________________
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

Sealing classes by default is a terrible idea IMHO. Fortunately, my faith in the Swift core team is strong enough so that I cannot believe that this has a chance of ever being implemented at all :)

Why do I think it's terrible? I do subclass classes even when they say that you shouldn't do it. I even monkey-patched a few classes in the past. Why? Not because I prefer hacking over clean coding, but to get the job done. Every few months or so I encounter a situation where such hacking attempts are the only feasible way to make something work. Or I use them during research activities or unofficial "feasibility studies". (If that's not the case for you, then maybe you are working in a different job than I. Monkey patching is rarely necessary if you make iPhone apps.) These are situations where everyone else just says "that's not possible". Yes, you can make that USB driver class stop spamming the console; yes, you can stop that library from crashing randomly.

There is so much more to say on this topic. Sealing classes is also bad because it prevents forms of experimental coding. It doesn't solve a real problem. How often have I seen bugs where someone subclassed a class that shouldn't be subclassed? That's so rare. But if all classes are sealed by default this will lead to far worse problems. When a developer subclasses a class, he usually has a reason. There already is a `final` keyword in Swift, and a dev really thinks that a class shouldn't be subclass-able, he can use it already. And if I subclass it from Objective-C anyways, then maybe I know what I'm doing?

And I'm not buying this "performance" argument. If you want better performance, write the hot functions in C or maybe even in assembler. The dynamic dispatch overhead is not the feature that makes programs bad or slow. It's quadratic algorithms (e.g. unnecessary nested loops), calling functions multiple times (e.g. if(a.foo.bar(x[2]) == "joo" || a.foo.bar(x[2]) == "fooo" || a.foo.bar(x[2]) == nil) { ... }), or just overly complex code: all of them have more impact than dynamic dispatch. Even worse for performance is unnecessary IO or using graphics APIs inefficiently. A good profiler can help a lot with these issues.

Swift should be designed for the real world, not for an ideal world that does not exist and that will never exist.

The design intent of much of Swift is to allow "free" coding within a module/file/type while encouraging programmers to think more carefully about their public interfaces. Module interfaces are the most serious and permanent of these interfaces. It's in keeping with that for declarations to make only minimal public guarantees and require the programmer to be more explicit about the things they want to allow.

Your arguments about patchability and performance could be applied to every feature in the language. They are essentially arguments for a fully-dynamic environment.

see Straw man - Wikipedia

Most OO languages do not seal seal modules (or the equivalent) by default. Forcing developers to add “final” does not seem onerous. If authors do not have time to audit their frameworks, the language should not pretend do it for them.

There's no reason to single out subclassing; for everything you can imagine, one programmer's caution will be another's paternalism. You're just making the argument here because you're used to a particular way of patching Objective-C code, one which will work regardless of this language decision;

That seems personal.

but most of the old ObjC techniques (e.g. accessing ivars reflectively) already won't work on Swift code without unsafe operations, and subclassing is a very tiny part of that problem.

And no, we do not and will not accept that performance-sensitive code can only possibly be written in C or assembly, or that algorithmic performance is the only thing worth worrying about, even for the language implementation.

Could many of the performance advantages of sealing could be gained through “whole application” optimization?T he benefits could far exceed what is possible with whole module optimization. It would probably be extremely difficult and hard to scale, but for packaged, signed applications, it should be possible some day.

···

On Jun 28, 2016, at 2:31 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 28, 2016, at 12:39 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

John.

-Michael

Am 28.06.2016 um 15:09 schrieb L. Mihalkovic via swift-evolution <swift-evolution@swift.org>:

Regards
LM
(From mobile)

On Jun 28, 2016, at 1:57 PM, Alejandro Martinez via swift-evolution <swift-evolution@swift.org> wrote:

Anton Zhilin: That is one of the points if I’m not mistaken. Sealed
means that with whole-module-optimization the compiler can optimise
more things as it can treat it as final for other modules.

L. Mihalkovic: Could you give an example of what exactly do you mean?
I know one of the reasons behind the proposal is to actually improve
those situations by forcing us to think more on customisation when
designing APIs.

In many situation it has been my experience that libraries can be extended DESPITE their authors, rather than only thanks to the skills the authors have shown in planning for the future. It is what happened to me with AlamoFire, where i was able to extend it because some cracks existed which let me do something the designers did not think about (to me it was a lack of imagination to not have anticipated what i wanted to do).

So if this can happen with a lib made by very experienced/talented developers, then imagine what happens with far less skilled developers.. it will mean having to copy code in order extend. It may sound pessimistic, but if u had seen as much bad code as i have seen, you might understand the view i am sharing.

What's worse is that objc is not particularly conducive to good software architecture (it is a bit like perl and javascript where anything can be touched from anywhere, and has a limited set of constructs compared to c++, scala, java, c#, swift). So i do not believe that it has prepared objc devs to suddenly become great code designers with a language that has multiples levels of scoping/nesting (i would not use most of the swift libs i have seen on github to teach software design).

Hence my conclusion that defaulting to sealed may be giving too much credit to the code that is currently available for reuse.

On Tue, Jun 28, 2016 at 12:44 PM, Anton Zhilin via swift-evolution >>>> <swift-evolution@swift.org> wrote:

Does `sealed` allow for any optimizations? Maybe somehow devirtualizing
method calls?

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

--
Alejandro Martinez
http://alejandromp.com
_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Sealing classes by default is a terrible idea IMHO. Fortunately, my faith in the Swift core team is strong enough so that I cannot believe that this has a chance of ever being implemented at all :)

Why do I think it's terrible? I do subclass classes even when they say that you shouldn't do it. I even monkey-patched a few classes in the past. Why? Not because I prefer hacking over clean coding, but to get the job done. Every few months or so I encounter a situation where such hacking attempts are the only feasible way to make something work. Or I use them during research activities or unofficial "feasibility studies". (If that's not the case for you, then maybe you are working in a different job than I. Monkey patching is rarely necessary if you make iPhone apps.) These are situations where everyone else just says "that's not possible". Yes, you can make that USB driver class stop spamming the console; yes, you can stop that library from crashing randomly.

There is so much more to say on this topic. Sealing classes is also bad because it prevents forms of experimental coding. It doesn't solve a real problem. How often have I seen bugs where someone subclassed a class that shouldn't be subclassed? That's so rare. But if all classes are sealed by default this will lead to far worse problems. When a developer subclasses a class, he usually has a reason. There already is a `final` keyword in Swift, and a dev really thinks that a class shouldn't be subclass-able, he can use it already. And if I subclass it from Objective-C anyways, then maybe I know what I'm doing?

And I'm not buying this "performance" argument. If you want better performance, write the hot functions in C or maybe even in assembler. The dynamic dispatch overhead is not the feature that makes programs bad or slow. It's quadratic algorithms (e.g. unnecessary nested loops), calling functions multiple times (e.g. if(a.foo.bar(x[2]) == "joo" || a.foo.bar(x[2]) == "fooo" || a.foo.bar(x[2]) == nil) { ... }), or just overly complex code: all of them have more impact than dynamic dispatch. Even worse for performance is unnecessary IO or using graphics APIs inefficiently. A good profiler can help a lot with these issues.

Swift should be designed for the real world, not for an ideal world that does not exist and that will never exist.

The design intent of much of Swift is to allow "free" coding within a module/file/type while encouraging programmers to think more carefully about their public interfaces. Module interfaces are the most serious and permanent of these interfaces. It's in keeping with that for declarations to make only minimal public guarantees and require the programmer to be more explicit about the things they want to allow.

Your arguments about patchability and performance could be applied to every feature in the language. They are essentially arguments for a fully-dynamic environment.

see Straw man - Wikipedia

What's the limiting argument? Why is it critical for practical programmers to be able to arbitrarily patch someone else's code, but only at the point where it calls public methods on public classes? That's a very strange idea in Swift, given how we encourage the use of structs and non-public types.

Most OO languages do not seal seal modules (or the equivalent) by default. Forcing developers to add “final” does not seem onerous. If authors do not have time to audit their frameworks, the language should not pretend do it for them.

Again, this could be an argument for making everything public by default. (Many OO languages essentially do.) What's the limiting argument?

Swift takes a consistent line here: the default rule across a module boundary is the rule that reserves the implementation the greatest flexibility in the future. Making classes final outside of the module gives the module the right to make the class final everywhere and to change the class's internal implementation to call different methods or change delegation patterns without worrying about how it affects a use-case that most programmers won't have considered. If they have considered it, of course, it is trivial for them to write that down, just as it is trivial for them to make the class public to begin with.

There's no reason to single out subclassing; for everything you can imagine, one programmer's caution will be another's paternalism. You're just making the argument here because you're used to a particular way of patching Objective-C code, one which will work regardless of this language decision;

That seems personal.

If there's another reason why this only applies to subclassing, I can't see it.

but most of the old ObjC techniques (e.g. accessing ivars reflectively) already won't work on Swift code without unsafe operations, and subclassing is a very tiny part of that problem.

And no, we do not and will not accept that performance-sensitive code can only possibly be written in C or assembly, or that algorithmic performance is the only thing worth worrying about, even for the language implementation.

Could many of the performance advantages of sealing could be gained through “whole application” optimization?T he benefits could far exceed what is possible with whole module optimization. It would probably be extremely difficult and hard to scale, but for packaged, signed applications, it should be possible some day.

Whole-program optimization relies on there being some step at which we can see all the code. We want to allow separate compilation of libraries, and we do not have a JIT.

The decision to make class methods polymorphic by default was always premised on being able to undo that in obvious cases where methods are never overridden. Making a class public so that clients can use it shouldn't cause significant performance degradations just because you forgot to also write "final".

John.

···

On Jun 28, 2016, at 2:20 PM, Christopher Kornher <ckornher@me.com> wrote:

On Jun 28, 2016, at 2:31 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 28, 2016, at 12:39 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

-1 for the fact that if all devs can write working code, fewer can do it in a clear structured fashion that is well designed for extensibility.

This sounds more like an argument for having sealed classes than not. As the proposal points out in the motivation, if the base class is not designed with subclassing in mind then overriding methods can result in unintended behavior (e.g. crashing, or other bugs).

But I think the counter argument is, what if you need to fix or workaround unintended behavior of the class you’re trying to use?

Typically you modify something open source - 99% of which is on GitHub. IMHO the best way is to either fork it and perhaps submit a pull request with the fix.

But I understand that this is not always possible...

···

On Jun 28, 2016, at 4:55 PM, Sean Heber via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 28, 2016, at 9:52 AM, Mark Lacey via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 27, 2016, at 9:10 PM, L. Mihalkovic via swift-evolution <swift-evolution@swift.org> wrote:

l8r
Sean

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

I do care about performance. For this reason I don't want a fully dynamic language. I disagree about the "significant performance degradations just because you forgot to also write `final`". I mentioned "performance" in my original post only because it would be the only convincing argument - if there were indeed superior performance when using `final`.

Of course, dynamic dispatch is much slower than static dispatch. But optimized code does not spend much time dispatching. If a method takes 3 seconds to complete, and from that 2 seconds are used for dynamically dispatching method calls, then I would say that it has not been optimized for performance yet. How would such a function look like? The function being dynamically dispatched should probably not be statically dispatched but inlined completely. And for the rare case that the dispatch type really makes all the difference, it's always possible to `final`ize (or `private`ize) some of the used methods.

-Michael

···

Am 29.06.2016 um 00:32 schrieb John McCall <rjmccall@apple.com>:

The decision to make class methods polymorphic by default was always premised on being able to undo that in obvious cases where methods are never overridden. Making a class public so that clients can use it shouldn't cause significant performance degradations just because you forgot to also write "final".

John.

I'm still unhappy about this "sealed by default" proposal. That really looks like premature optimization to me. Instead there should be some `sealed` keyword. Maybe it should be called `applepublic` :-p Everyone will understand!

`sealed` classes should be a special optimization used by optimizing developers who ask for it. Don't make it an unwanted and un-asked-for default optimization. The people who care for optimization much will learn about `sealed` and be able to apply the concept in both cases. The people who don't care about performance will just be disappointed by the "implicitly sealed" behavior. And with this proposal, when I read `unsealed` I can never know: "did this developer intend me to be able to subclass this class? or did he just not want to restrict me unnecessarily?" The documenting aspect of `unsealed` is so small.

And `sealed` is just an optimization; IMHO the magic of static dispatch lies in final classes or final methods. Sealing everything by default just marks many classes and methods as implicitly final (because it can be proven that they are not subclassed). I just don't think that all these theoretical performance improvements are really worth the trouble in practice.

I'm confused about why you think this is so much of a problem. Do you really anticipate writing so many Swift libraries with public classes?

John.

···

On Jun 29, 2016, at 12:05 PM, Michael Peternell <michael.peternell@gmx.at> wrote:

-Michael

Am 29.06.2016 um 20:39 schrieb Vladimir.S via swift-evolution <swift-evolution@swift.org>:

How about `public(extensible)` ?

On 29.06.2016 21:32, John McCall via swift-evolution wrote:

On Jun 29, 2016, at 11:16 AM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:
Do you mean `public(unsealed)`? Because `internal(unsealed)` doesn't really make sense. `internal` declarations are always sealed.

Right.

If "sealed" is the default behavior for public classes and methods — and I don't think the modifier is worth adding unless it's the default — then we need a way of "unsealing" classes and methods that's fairly pithy. I don't think a parenthesized spelling is good enough for that. And we should try to make the positive form ("can be overridden") shorter than the negative ("cannot be overridden"), because the latter will not usually be written.

To me, the ideal spelling would be usable in place of "public". If it does have to be stacked with "public", then I think it ought to be pretty short.

"communal"? :)

"open" doesn't carry quite the right meaning, and it would need to be paired with "public", I think.

John.

-Michael

Am 29.06.2016 um 20:11 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

Do we really need a new keyword? Since we already have syntax like `internal(set)` couldn't we do `internal(unsealed)`, etc.

On Wed, Jun 29, 2016 at 12:21 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 29, 2016, at 12:15 PM, Michael Peternell <michael.peternell@gmx.at> wrote:

Am 29.06.2016 um 15:54 schrieb David Sweeris via swift-evolution <swift-evolution@swift.org>:

+1 for the concept of a "sealed” class.
-1 for making it default.

Aren't sealed classes already implemented? I think the keyword is `final`..
So there is nothing left to do :)

No, `final` doesn’t allow for any subclassing, but `sealed` allows for subclassing within your module (where you can presumably write more efficient code based on knowledge of each subclass).

- Dave Sweeris
_______________________________________________
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

Hmm. I started to work out an example with these as separate modifiers, and I think I understand the need to combine them in some way.

I wonder if just "extensible" would be good enough. It is a term that's used in API descriptions.

John.

···

On Jun 29, 2016, at 11:39 AM, Vladimir.S <svabox@gmail.com> wrote:
How about `public(extensible)` ?

How about `public(extensible)` ?

Hmm. I started to work out an example with these as separate modifiers, and I think I understand the need to combine them in some way.

I wonder if just "extensible" would be good enough. It is a term that's used in API descriptions.

'extensible' is a broad term. That has both advantages and disadvantages.

An advantage is that it can be used to mean both 'subclassable' / 'inheritable' as well as 'overridable'. This would allow us to use a single keyword, while sealing methods by default in 'extensible' classes.

A disadvantage is that is isn't immediately clear what kind of extensibility is provided - you just have to know what the keyword means in a specific context.

Perhaps a larger disadvantage is that 'extensible' shares a root with 'extension' and all public classes are open to extension in Swift.

-Matthew

···

Sent from my iPad
On Jun 29, 2016, at 2:54 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 29, 2016, at 11:39 AM, Vladimir.S <svabox@gmail.com> wrote:

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

> How about `public(extensible)` ?

Hmm. I started to work out an example with these as separate modifiers,
and I think I understand the need to combine them in some way.

I wonder if just "extensible" would be good enough. It is a term that's
used in API descriptions.

This particular word is unfortunate because it has nothing to do with an
extension, which shares the same etymological root.

···

On Wed, Jun 29, 2016 at 2:54 PM, John McCall via swift-evolution < swift-evolution@swift.org> wrote:

> On Jun 29, 2016, at 11:39 AM, Vladimir.S <svabox@gmail.com> wrote:

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

I'm still unhappy about this "sealed by default" proposal. That really looks like premature optimization to me. Instead there should be some `sealed` keyword. Maybe it should be called `applepublic` :-p Everyone will understand!

`sealed` classes should be a special optimization used by optimizing developers who ask for it. Don't make it an unwanted and un-asked-for default optimization. The people who care for optimization much will learn about `sealed` and be able to apply the concept in both cases. The people who don't care about performance will just be disappointed by the "implicitly sealed" behavior. And with this proposal, when I read `unsealed` I can never know: "did this developer intend me to be able to subclass this class? or did he just not want to restrict me unnecessarily?" The documenting aspect of `unsealed` is so small.

And `sealed` is just an optimization; IMHO the magic of static dispatch lies in final classes or final methods. Sealing everything by default just marks many classes and methods as implicitly final (because it can be proven that they are not subclassed). I just don't think that all these theoretical performance improvements are really worth the trouble in practice.

-Michael

···

Am 29.06.2016 um 20:39 schrieb Vladimir.S via swift-evolution <swift-evolution@swift.org>:

How about `public(extensible)` ?

On 29.06.2016 21:32, John McCall via swift-evolution wrote:

On Jun 29, 2016, at 11:16 AM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:
Do you mean `public(unsealed)`? Because `internal(unsealed)` doesn't really make sense. `internal` declarations are always sealed.

Right.

If "sealed" is the default behavior for public classes and methods — and I don't think the modifier is worth adding unless it's the default — then we need a way of "unsealing" classes and methods that's fairly pithy. I don't think a parenthesized spelling is good enough for that. And we should try to make the positive form ("can be overridden") shorter than the negative ("cannot be overridden"), because the latter will not usually be written.

To me, the ideal spelling would be usable in place of "public". If it does have to be stacked with "public", then I think it ought to be pretty short.

"communal"? :)

"open" doesn't carry quite the right meaning, and it would need to be paired with "public", I think.

John.

-Michael

Am 29.06.2016 um 20:11 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

Do we really need a new keyword? Since we already have syntax like `internal(set)` couldn't we do `internal(unsealed)`, etc.

On Wed, Jun 29, 2016 at 12:21 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 29, 2016, at 12:15 PM, Michael Peternell <michael.peternell@gmx.at> wrote:

Am 29.06.2016 um 15:54 schrieb David Sweeris via swift-evolution <swift-evolution@swift.org>:

+1 for the concept of a "sealed” class.
-1 for making it default.

Aren't sealed classes already implemented? I think the keyword is `final`..
So there is nothing left to do :)

No, `final` doesn’t allow for any subclassing, but `sealed` allows for subclassing within your module (where you can presumably write more efficient code based on knowledge of each subclass).

- Dave Sweeris
_______________________________________________
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

I'm still unhappy about this "sealed by default" proposal. That really
looks like premature optimization to me. Instead there should be some
`sealed` keyword. Maybe it should be called `applepublic` :-p Everyone
will understand!

I understand your point of view. But I also think about the proposal as forcing the developer of public(! i.e. usually which exported from some framework) to carefully think if he/she really wants to allow exported types will be extensible. Not just about performance.

And as was mentioned, 'sealed' is not 'final' : you can extend the sealed type in internal scope, but it will be final for public scope. (If I don't miss something)

But, yes, I'm also not sure if we should seal by default and not introduce `public(final)` or `public(sealed)` access modifier for those who explicitly don't want to allow extension of exported class.

···

On 29.06.2016 22:05, Michael Peternell wrote:

`sealed` classes should be a special optimization used by optimizing
developers who ask for it. Don't make it an unwanted and un-asked-for
default optimization. The people who care for optimization much will
learn about `sealed` and be able to apply the concept in both cases. The
people who don't care about performance will just be disappointed by the
"implicitly sealed" behavior. And with this proposal, when I read
`unsealed` I can never know: "did this developer intend me to be able to
subclass this class? or did he just not want to restrict me
unnecessarily?" The documenting aspect of `unsealed` is so small.

And `sealed` is just an optimization; IMHO the magic of static dispatch
lies in final classes or final methods. Sealing everything by default
just marks many classes and methods as implicitly final (because it can
be proven that they are not subclassed). I just don't think that all
these theoretical performance improvements are really worth the trouble
in practice.

-Michael

Am 29.06.2016 um 20:39 schrieb Vladimir.S via swift-evolution >> <swift-evolution@swift.org>:

How about `public(extensible)` ?

On 29.06.2016 21:32, John McCall via swift-evolution wrote:

On Jun 29, 2016, at 11:16 AM, Michael Peternell via
swift-evolution <swift-evolution@swift.org> wrote: Do you mean
`public(unsealed)`? Because `internal(unsealed)` doesn't really
make sense. `internal` declarations are always sealed.

Right.

If "sealed" is the default behavior for public classes and methods —
and I don't think the modifier is worth adding unless it's the
default — then we need a way of "unsealing" classes and methods
that's fairly pithy. I don't think a parenthesized spelling is good
enough for that. And we should try to make the positive form ("can
be overridden") shorter than the negative ("cannot be overridden"),
because the latter will not usually be written.

To me, the ideal spelling would be usable in place of "public". If
it does have to be stacked with "public", then I think it ought to
be pretty short.

"communal"? :)

"open" doesn't carry quite the right meaning, and it would need to
be paired with "public", I think.

John.

-Michael

Am 29.06.2016 um 20:11 schrieb Xiaodi Wu via swift-evolution >>>>> <swift-evolution@swift.org>:

Do we really need a new keyword? Since we already have syntax
like `internal(set)` couldn't we do `internal(unsealed)`, etc.

On Wed, Jun 29, 2016 at 12:21 PM, David Sweeris via >>>>> swift-evolution <swift-evolution@swift.org> wrote:

On Jun 29, 2016, at 12:15 PM, Michael Peternell >>>>>> <michael.peternell@gmx.at> wrote:

Am 29.06.2016 um 15:54 schrieb David Sweeris via >>>>>>> swift-evolution <swift-evolution@swift.org>:

+1 for the concept of a "sealed” class. -1 for making it
default.

Aren't sealed classes already implemented? I think the keyword
is `final`.. So there is nothing left to do :)

No, `final` doesn’t allow for any subclassing, but `sealed`
allows for subclassing within your module (where you can
presumably write more efficient code based on knowledge of each
subclass).

- Dave Sweeris _______________________________________________
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

Regards
(From mobile)

How about `public(extensible)` ?

Do you mean `public(unsealed)`? Because `internal(unsealed)` doesn't really make sense. `internal` declarations are always sealed.

Right.

If "sealed" is the default behavior for public classes and methods — and I don't think the modifier is worth adding unless it's the default

What a jump... I am very curious about this rational that seems so obvious to you?

···

On Jun 29, 2016, at 8:39 PM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:
On 29.06.2016 21:32, John McCall via swift-evolution wrote:

On Jun 29, 2016, at 11:16 AM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

— then we need a way of "unsealing" classes and methods that's fairly pithy. I don't think a parenthesized spelling is good enough for that. And we should try to make the positive form ("can be overridden") shorter than the negative ("cannot be overridden"), because the latter will not usually be written.

To me, the ideal spelling would be usable in place of "public". If it does have to be stacked with "public", then I think it ought to be pretty short.

"communal"? :)

"open" doesn't carry quite the right meaning, and it would need to be paired with "public", I think.

John.

-Michael

Am 29.06.2016 um 20:11 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

Do we really need a new keyword? Since we already have syntax like `internal(set)` couldn't we do `internal(unsealed)`, etc.

On Wed, Jun 29, 2016 at 12:21 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:
On Jun 29, 2016, at 12:15 PM, Michael Peternell <michael.peternell@gmx.at> wrote:

Am 29.06.2016 um 15:54 schrieb David Sweeris via swift-evolution <swift-evolution@swift.org>:

+1 for the concept of a "sealed” class.
-1 for making it default.

Aren't sealed classes already implemented? I think the keyword is `final`..
So there is nothing left to do :)

No, `final` doesn’t allow for any subclassing, but `sealed` allows for subclassing within your module (where you can presumably write more efficient code based on knowledge of each subclass).

- Dave Sweeris
_______________________________________________
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