[Returned for revision] SE-0117: Default classes to be non-subclassable publicly

2016/07/16 21:37、Jean-Daniel Dupas <mailing@xenonium.com> のメール:

2016/07/15 16:37、Riley Testut via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> のメッセージ:

FWIW, I'm still against this proposal, but since it will be accepted regardless, here are my thoughts:

• Open keyword is significantly better.
• Members should be *open* by default, and final should be opt-in. If you're opening up a class for subclassing, my gut says you should allow the client to do as they wish.

If you have a class that was not open yet, just making it open wouldn't expose any members: it would then just be subclassable.

If the act of making the class open doesn't implicitly make overriding possible, well all you can do then is add methods, and that can be done with extensions anyways, so it's not as useful and makes the public open class {} pattern just by itself not so useful imho... :grimacing:

Also, the keyword 'open' itself may imply 'hey I'm open, please do what you want with my public members', whereas 'subclassable' is more specific in intention... (but that's just me, so n=1 and all that)

TLDR; +1 to the above: simpler is better and defaulting to overridable for public members on an open class is simpler... invariants can be protected by the 'final' keyword.

If we were to default to non-overridable, a more consistent 'open' on the method is preferred over overridable for me... open class, open method... much better imho...

Do we really need an open keyword ?

As already said, if open does nothing more than allowing the class to be subclassed, why not simply make the class subclassable if it contains at least one overridable member ?

Thats a good point actually… but looks like Review #2 has already started… and 'open' is available for both class and method there… I suppose its the whole "default to safe", just in case someone made one method 'open' they may not have intended to actually make the whole class open… (also see below)

In case we require an open keyword, what would happen if someone mark a member overridable, but does not make the class open ? Will the compiler emit an error, or make the class implicitly « open » ?

In proposal #2 looks like it would generate an error, but Xiaodi Wu has said that it should be allowed and not generate an error per SE-0025 <https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md&gt;\.
<https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md#complications-with-private-types&gt;Take a look at <https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md#complications-with-private-types&gt;: "The compiler should not warn when a broader level of access control is used within a type with more restrictive access, such as internal within a private type."

- Andre

···

Le 16 juil. 2016 à 00:31, Andre Elder via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

What happens if I want an `internal` subclass of an `open` class?

···

On Sat, Jul 16, 2016 at 10:09 AM, David Hart via swift-evolution < swift-evolution@swift.org> wrote:

Swift has always gone towards making declarations explicit to read. Having
open on thé class declaration makes it so you don't have to go hunting into
its members to see if it contains an open member.

Other comments inline:

On 16 Jul 2016, at 14:49, Andre via swift-evolution < > swift-evolution@swift.org> wrote:

2016/07/16 21:37、Jean-Daniel Dupas <mailing@xenonium.com> のメール:

Le 16 juil. 2016 à 00:31, Andre Elder via swift-evolution < > swift-evolution@swift.org> a écrit :

2016/07/15 16:37、Riley Testut via swift-evolution <
swift-evolution@swift.org> のメッセージ:

FWIW, I'm still against this proposal, but since it will be accepted
regardless, here are my thoughts:

• Open keyword is significantly better.
• Members should be *open* by default, and final should be opt-in. If
you're opening up a class for subclassing, my gut says you should allow the
client to do as they wish.

If you have a class that was not open yet, just making it open wouldn't
expose any members: it would then just be subclassable.

If the act of making the class open doesn't implicitly make overriding
possible, well all you can do then is add methods, and that can be done
with extensions anyways, so it's not as useful and makes the *public open
class {}* pattern *just* by itself not so useful imho... :grimacing:

Also, the keyword 'open' itself may imply 'hey I'm open, please do what
you want with my public members', whereas 'subclassable' is more specific
in intention... (but that's just me, so n=1 and all that)

TLDR; +1 to the above: simpler is better and defaulting to overridable for
public members on an open class is simpler... invariants can be protected
by the 'final' keyword.

If we were to default to non-overridable, a more consistent 'open' on the
method is preferred over overridable for me... open class, open method...
much better imho...

Do we really need an open keyword ?

As already said, if open does nothing more than allowing the class to be
subclassed, why not simply make the class subclassable if it contains at
least one overridable member ?

Thats a good point actually… but looks like Review #2 has already started…
and 'open' is available for both class and method there… I suppose its the
whole "default to safe", just in case someone made one method 'open' they
may not have intended to actually make the whole class open… (also see
below)

In case we require an open keyword, what would happen if someone mark a
member overridable, but does not make the class open ? Will the compiler
emit an error, or make the class implicitly « open » ?

In proposal #2 looks like it would generate an error, but Xiaodi Wu has
said that it should be allowed and not generate an error per SE-0025
<https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md&gt;
.

<https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md#complications-with-private-types&gt;Take
a look at
<https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md#complications-with-private-types&gt;:
"The compiler should not warn when a broader level of access control is
used within a type with more restrictive access, such as internal within
a private type."

I'm fairly sure that does not apply to open as it's fairly orthogonal to
other access control modifiers.

- Andre

_______________________________________________
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

Sent from my iPhone

Yes, sorry, my point was that this consideration isn't spelled out.

Another question is whether or not making a subclass of an open class public by default is what we want. I see why it would be, I just think that it is a wrinkle to default to internal otherwise but not here.

I can't think of any good reason to assume a specific class should be public just because it is a subclass of an open class. The internal default would still be the right default in this case.

Right, there's no new restriction here. Of course you can make a private or internal subclass of a public open class — otherwise, you'd have to publicize every subclass of (say) UIViewController.

John.

···

On Jul 16, 2016, at 9:32 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:
On Jul 16, 2016, at 10:59 AM, T.J. Usiyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Sat, Jul 16, 2016 at 10:32 AM, Karl <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:

> On 16 Jul 2016, at 16:10, T.J. Usiyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>
> What happens if I want an `internal` subclass of an `open` class?

That should be allowable. You may want some optimised implementations, similar to how Apple used class-clusters in Obj-C. I don’t think that same pattern is exactly possible in Swift (I don’t think a class can set ‘self’ in its initialiser, or at least it couldn’t in Swift 1). But the same principle applies - you may want a public class which you don’t allow others to subclass, but you might have a static method or other function which returns an internal optimised implementation.

If you used a protocol rather than a concrete type in that case, theoretically others could conform to it and throw their own objects back at your code, which goes against the point of this proposal.

We might think about creating ‘sealed’ protocols, too.

Karl

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

"open is invalid on declarations that are not also public (see the Alternatives discussion for rationale)."

+

"If an open class inherits an open method from a superclass, that method remains open. If it overrides an open method from a superclass, the override is implicitly open if it is not final."

I understand that the intent is probably not to say that subclasses are public by default. My point is that those two statements, without an explicit spelling out of the implicit access level, could lead me to believe that subclasses are implicitly public by default. It is open to interpretation. Neither the prose nor the code examples address it.

I see your general point. I'll think about how to re-word this; it may be sufficient to just remove the requirement that open methods appear in open classes. Suffice it for me to say now, officially, that this proposal does not require classes to be public or open just because they override open methods from an open superclass.

John.

···

On Jul 16, 2016, at 11:03 AM, T.J. Usiyan <griotspeak@gmail.com> wrote:

On Sat, Jul 16, 2016 at 1:35 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Jul 16, 2016, at 9:32 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Sent from my iPhone

On Jul 16, 2016, at 10:59 AM, T.J. Usiyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Yes, sorry, my point was that this consideration isn't spelled out.

Another question is whether or not making a subclass of an open class public by default is what we want. I see why it would be, I just think that it is a wrinkle to default to internal otherwise but not here.

I can't think of any good reason to assume a specific class should be public just because it is a subclass of an open class. The internal default would still be the right default in this case.

Right, there's no new restriction here. Of course you can make a private or internal subclass of a public open class — otherwise, you'd have to publicize every subclass of (say) UIViewController.

John.

On Sat, Jul 16, 2016 at 10:32 AM, Karl <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:

> On 16 Jul 2016, at 16:10, T.J. Usiyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>
> What happens if I want an `internal` subclass of an `open` class?

That should be allowable. You may want some optimised implementations, similar to how Apple used class-clusters in Obj-C. I don’t think that same pattern is exactly possible in Swift (I don’t think a class can set ‘self’ in its initialiser, or at least it couldn’t in Swift 1). But the same principle applies - you may want a public class which you don’t allow others to subclass, but you might have a static method or other function which returns an internal optimised implementation.

If you used a protocol rather than a concrete type in that case, theoretically others could conform to it and throw their own objects back at your code, which goes against the point of this proposal.

We might think about creating ‘sealed’ protocols, too.

Karl

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

Yes, sorry, my point was that this consideration isn't spelled out.

Another question is whether or not making a subclass of an open class public by default is what we want. I see why it would be, I just think that it is a wrinkle to default to internal otherwise but not here.

I can't think of any good reason to assume a specific class should be public just because it is a subclass of an open class. The internal default would still be the right default in this case.

···

Sent from my iPhone

On Jul 16, 2016, at 10:59 AM, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:

On Sat, Jul 16, 2016 at 10:32 AM, Karl <razielim@gmail.com> wrote:

> On 16 Jul 2016, at 16:10, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:
>
> What happens if I want an `internal` subclass of an `open` class?

That should be allowable. You may want some optimised implementations, similar to how Apple used class-clusters in Obj-C. I don’t think that same pattern is exactly possible in Swift (I don’t think a class can set ‘self’ in its initialiser, or at least it couldn’t in Swift 1). But the same principle applies - you may want a public class which you don’t allow others to subclass, but you might have a static method or other function which returns an internal optimised implementation.

If you used a protocol rather than a concrete type in that case, theoretically others could conform to it and throw their own objects back at your code, which goes against the point of this proposal.

We might think about creating ‘sealed’ protocols, too.

Karl

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

Swift has always gone towards making declarations explicit to read. Having
open on thé class declaration makes it so you don't have to go hunting into
its members to see if it contains an open member.

Other comments inline:

2016/07/16 21:37、Jean-Daniel Dupas <mailing@xenonium.com> のメール:

2016/07/15 16:37、Riley Testut via swift-evolution <
swift-evolution@swift.org> のメッセージ:

FWIW, I'm still against this proposal, but since it will be accepted
regardless, here are my thoughts:

• Open keyword is significantly better.
• Members should be *open* by default, and final should be opt-in. If
you're opening up a class for subclassing, my gut says you should allow the
client to do as they wish.

If you have a class that was not open yet, just making it open wouldn't
expose any members: it would then just be subclassable.

If the act of making the class open doesn't implicitly make overriding
possible, well all you can do then is add methods, and that can be done
with extensions anyways, so it's not as useful and makes the *public open
class {}* pattern *just* by itself not so useful imho... :grimacing:

Also, the keyword 'open' itself may imply 'hey I'm open, please do what
you want with my public members', whereas 'subclassable' is more specific
in intention... (but that's just me, so n=1 and all that)

TLDR; +1 to the above: simpler is better and defaulting to overridable for
public members on an open class is simpler... invariants can be protected
by the 'final' keyword.

If we were to default to non-overridable, a more consistent 'open' on the
method is preferred over overridable for me... open class, open method...
much better imho...

Do we really need an open keyword ?

As already said, if open does nothing more than allowing the class to be
subclassed, why not simply make the class subclassable if it contains at
least one overridable member ?

Thats a good point actually… but looks like Review #2 has already started…
and 'open' is available for both class and method there… I suppose its the
whole "default to safe", just in case someone made one method 'open' they
may not have intended to actually make the whole class open… (also see
below)

In case we require an open keyword, what would happen if someone mark a
member overridable, but does not make the class open ? Will the compiler
emit an error, or make the class implicitly « open » ?

In proposal #2 looks like it would generate an error, but Xiaodi Wu has
said that it should be allowed and not generate an error per SE-0025
<https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md&gt;
.

<https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md#complications-with-private-types&gt;Take
a look at
<https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md#complications-with-private-types&gt;:
"The compiler should not warn when a broader level of access control is
used within a type with more restrictive access, such as internal within
a private type."

I'm fairly sure that does not apply to open as it's fairly orthogonal to
other access control modifiers.

I agree that the statement in SE-0025 by itself doesn't necessary apply to
`open` because they are somewhat orthogonal. But the stated rationale in
SE-0025 applies equally to `open`, so I think this proposal would be
improved by having `open` behave similarly in this respect. Here's why:

The rationale stated in SE-0025 is that it allows a person who controls the
type to design as though it will have broader access than it actually does.
For instance, I can design an internal class as though it will be public,
and when I'm satisfied with it, I can flip the switch and actually make it
public by adding a single access modifier. That rationale falls down for
classes if I cannot design a `public open` class without already making it
`public open`.

···

On Sat, Jul 16, 2016 at 9:09 AM, David Hart via swift-evolution < swift-evolution@swift.org> wrote:

On 16 Jul 2016, at 14:49, Andre via swift-evolution < > swift-evolution@swift.org> wrote:
Le 16 juil. 2016 à 00:31, Andre Elder via swift-evolution < > swift-evolution@swift.org> a écrit :

- Andre

_______________________________________________
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

Yes, sorry, my point was that this consideration isn't spelled out.

Another question is whether or not making a subclass of an open class
public by default is what we want. I see why it would be, I just think that
it is a wrinkle to default to internal otherwise but not here.

···

On Sat, Jul 16, 2016 at 10:32 AM, Karl <razielim@gmail.com> wrote:

> On 16 Jul 2016, at 16:10, T.J. Usiyan via swift-evolution < > swift-evolution@swift.org> wrote:
>
> What happens if I want an `internal` subclass of an `open` class?

That should be allowable. You may want some optimised implementations,
similar to how Apple used class-clusters in Obj-C. I don’t think that same
pattern is exactly possible in Swift (I don’t think a class can set ‘self’
in its initialiser, or at least it couldn’t in Swift 1). But the same
principle applies - you may want a public class which you don’t allow
others to subclass, but you might have a static method or other function
which returns an internal optimised implementation.

If you used a protocol rather than a concrete type in that case,
theoretically others could conform to it and throw their own objects back
at your code, which goes against the point of this proposal.

We might think about creating ‘sealed’ protocols, too.

Karl

"open is invalid on declarations that are not also public (see the Alternatives discussion for rationale)."

+

"If an open class inherits an open method from a superclass, that method remains open. If it overrides an open method from a superclass, the override is implicitly open if it is not final."

I understand that the intent is probably not to say that subclasses are public by default. My point is that those two statements, without an explicit spelling out of the implicit access level, could lead me to believe that subclasses are implicitly public by default. It is open to interpretation. Neither the prose nor the code examples address it.

I see your general point. I'll think about how to re-word this; it may be sufficient to just remove the requirement that open methods appear in open classes. Suffice it for me to say now, officially, that this proposal does not require classes to be public or open just because they override open methods from an open superclass.

It might be barely sufficient solely to remove the requirement that open methods appear in open classes. However, if my subclass is internal, I shouldn't be required to declare a `public override` of an open method just to satisfy the rules for `open`, which would be forced by the rule that `open` is invalid on declarations that are not also `public`

This rule only applies to explicit uses of "open". A method that is implicitly open due to overriding does not have this restriction.

In general, my intent in writing this proposal was to cover the important interactions, not to write a fully precise specification. The general rule about overrides having to be at least as accessible as the minimum of their class and their overridden method still applies, superseded only by the rule that it is acceptable to drop the "open" on a public open override.

combined with the rule that overrides of an open method are by default open.

This would degrade the developer experience significantly, since a beginning developer writing only internal subclasses for their own app would now be required to litter either `public override` or `final override` throughout their code in the ordinary course of subclassing. On reconsideration, it might be best if overrides are not implicitly open.

I continue to think "override" is sufficient communication here. We're not going to have a model where the inherited open API of the superclass becomes non-open in the subclass. We don't want the mere existence of an override in the subclass to change that because it's a fairly core goal that the existence of an override (at least one which doesn't covariantly refine the type) in a subclass should not affect source/binary compatibility.

John.

···

On Jul 16, 2016, at 11:48 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
On Sat, Jul 16, 2016 at 1:16 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jul 16, 2016, at 11:03 AM, T.J. Usiyan <griotspeak@gmail.com <mailto:griotspeak@gmail.com>> wrote:

John.

On Sat, Jul 16, 2016 at 1:35 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Jul 16, 2016, at 9:32 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Sent from my iPhone

On Jul 16, 2016, at 10:59 AM, T.J. Usiyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Yes, sorry, my point was that this consideration isn't spelled out.

Another question is whether or not making a subclass of an open class public by default is what we want. I see why it would be, I just think that it is a wrinkle to default to internal otherwise but not here.

I can't think of any good reason to assume a specific class should be public just because it is a subclass of an open class. The internal default would still be the right default in this case.

Right, there's no new restriction here. Of course you can make a private or internal subclass of a public open class — otherwise, you'd have to publicize every subclass of (say) UIViewController.

John.

On Sat, Jul 16, 2016 at 10:32 AM, Karl <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:

> On 16 Jul 2016, at 16:10, T.J. Usiyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>
> What happens if I want an `internal` subclass of an `open` class?

That should be allowable. You may want some optimised implementations, similar to how Apple used class-clusters in Obj-C. I don’t think that same pattern is exactly possible in Swift (I don’t think a class can set ‘self’ in its initialiser, or at least it couldn’t in Swift 1). But the same principle applies - you may want a public class which you don’t allow others to subclass, but you might have a static method or other function which returns an internal optimised implementation.

If you used a protocol rather than a concrete type in that case, theoretically others could conform to it and throw their own objects back at your code, which goes against the point of this proposal.

We might think about creating ‘sealed’ protocols, too.

Karl

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

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

"open is invalid on declarations that are not also public (see the
Alternatives discussion for rationale)."
+

"If an open class inherits an open method from a superclass, that method
remains open. If it overrides an open method from a superclass, the
override is implicitly open if it is not final."

I understand that the intent is probably not to say that subclasses are
public by default. My point is that those two statements, without an
explicit spelling out of the implicit access level, could lead me to
believe that subclasses are implicitly public by default. It is open to
interpretation. Neither the prose nor the code examples address it.

I see your general point. I'll think about how to re-word this; it may be
sufficient to just remove the requirement that open methods appear in open
classes. Suffice it for me to say now, officially, that this proposal does
not require classes to be public or open just because they override open
methods from an open superclass.

It might be barely sufficient solely to remove the requirement that open
methods appear in open classes. However, if my subclass is internal, I
shouldn't be required to declare a `public override` of an open method just
to satisfy the rules for `open`, which would be forced by the rule that
`open` is invalid on declarations that are not also `public` combined with
the rule that overrides of an open method are by default open.

This would degrade the developer experience significantly, since a
beginning developer writing only internal subclasses for their own app
would now be required to litter either `public override` or `final
override` throughout their code in the ordinary course of subclassing. On
reconsideration, it might be best if overrides are not implicitly open.

···

On Sat, Jul 16, 2016 at 1:16 PM, John McCall via swift-evolution < swift-evolution@swift.org> wrote:

On Jul 16, 2016, at 11:03 AM, T.J. Usiyan <griotspeak@gmail.com> wrote:

John.

On Sat, Jul 16, 2016 at 1:35 PM, John McCall <rjmccall@apple.com> wrote:

On Jul 16, 2016, at 9:32 AM, Matthew Johnson via swift-evolution < >> swift-evolution@swift.org> wrote:
Sent from my iPhone

On Jul 16, 2016, at 10:59 AM, T.J. Usiyan via swift-evolution < >> swift-evolution@swift.org> wrote:

Yes, sorry, my point was that this consideration isn't spelled out.

Another question is whether or not making a subclass of an open class
public by default is what we want. I see why it would be, I just think that
it is a wrinkle to default to internal otherwise but not here.

I can't think of any good reason to assume a specific class should be
public just because it is a subclass of an open class. The internal
default would still be the right default in this case.

Right, there's no new restriction here. Of course you can make a private
or internal subclass of a public open class — otherwise, you'd have to
publicize every subclass of (say) UIViewController.

John.

On Sat, Jul 16, 2016 at 10:32 AM, Karl <razielim@gmail.com> wrote:

> On 16 Jul 2016, at 16:10, T.J. Usiyan via swift-evolution < >>> swift-evolution@swift.org> wrote:
>
> What happens if I want an `internal` subclass of an `open` class?

That should be allowable. You may want some optimised implementations,
similar to how Apple used class-clusters in Obj-C. I don’t think that same
pattern is exactly possible in Swift (I don’t think a class can set ‘self’
in its initialiser, or at least it couldn’t in Swift 1). But the same
principle applies - you may want a public class which you don’t allow
others to subclass, but you might have a static method or other function
which returns an internal optimised implementation.

If you used a protocol rather than a concrete type in that case,
theoretically others could conform to it and throw their own objects back
at your code, which goes against the point of this proposal.

We might think about creating ‘sealed’ protocols, too.

Karl

_______________________________________________
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

"open is invalid on declarations that are not also public (see the
Alternatives discussion for rationale)."

···

+

"If an open class inherits an open method from a superclass, that method
remains open. If it overrides an open method from a superclass, the
override is implicitly open if it is not final."

I understand that the intent is probably not to say that subclasses are
public by default. My point is that those two statements, without an
explicit spelling out of the implicit access level, could lead me to
believe that subclasses are implicitly public by default. It is open to
interpretation. Neither the prose nor the code examples address it.

On Sat, Jul 16, 2016 at 1:35 PM, John McCall <rjmccall@apple.com> wrote:

On Jul 16, 2016, at 9:32 AM, Matthew Johnson via swift-evolution < > swift-evolution@swift.org> wrote:
Sent from my iPhone

On Jul 16, 2016, at 10:59 AM, T.J. Usiyan via swift-evolution < > swift-evolution@swift.org> wrote:

Yes, sorry, my point was that this consideration isn't spelled out.

Another question is whether or not making a subclass of an open class
public by default is what we want. I see why it would be, I just think that
it is a wrinkle to default to internal otherwise but not here.

I can't think of any good reason to assume a specific class should be
public just because it is a subclass of an open class. The internal
default would still be the right default in this case.

Right, there's no new restriction here. Of course you can make a private
or internal subclass of a public open class — otherwise, you'd have to
publicize every subclass of (say) UIViewController.

John.

On Sat, Jul 16, 2016 at 10:32 AM, Karl <razielim@gmail.com> wrote:

> On 16 Jul 2016, at 16:10, T.J. Usiyan via swift-evolution < >> swift-evolution@swift.org> wrote:
>
> What happens if I want an `internal` subclass of an `open` class?

That should be allowable. You may want some optimised implementations,
similar to how Apple used class-clusters in Obj-C. I don’t think that same
pattern is exactly possible in Swift (I don’t think a class can set ‘self’
in its initialiser, or at least it couldn’t in Swift 1). But the same
principle applies - you may want a public class which you don’t allow
others to subclass, but you might have a static method or other function
which returns an internal optimised implementation.

If you used a protocol rather than a concrete type in that case,
theoretically others could conform to it and throw their own objects back
at your code, which goes against the point of this proposal.

We might think about creating ‘sealed’ protocols, too.

Karl

_______________________________________________
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

"open is invalid on declarations that are not also public (see the
Alternatives discussion for rationale)."
+

"If an open class inherits an open method from a superclass, that method
remains open. If it overrides an open method from a superclass, the
override is implicitly open if it is not final."

I understand that the intent is probably not to say that subclasses are
public by default. My point is that those two statements, without an
explicit spelling out of the implicit access level, could lead me to
believe that subclasses are implicitly public by default. It is open to
interpretation. Neither the prose nor the code examples address it.

I see your general point. I'll think about how to re-word this; it may
be sufficient to just remove the requirement that open methods appear in
open classes. Suffice it for me to say now, officially, that this proposal
does not require classes to be public or open just because they override
open methods from an open superclass.

It might be barely sufficient solely to remove the requirement that open
methods appear in open classes. However, if my subclass is internal, I
shouldn't be required to declare a `public override` of an open method just
to satisfy the rules for `open`, which would be forced by the rule that
`open` is invalid on declarations that are not also `public` combined with
the rule that overrides of an open method are by default open.

This would degrade the developer experience significantly, since a
beginning developer writing only internal subclasses for their own app
would now be required to litter either `public override` or `final
override` throughout their code in the ordinary course of subclassing. On
reconsideration, it might be best if overrides are not implicitly open.

I should add: independent of the issue above for internal subclasses in
apps that don't vend an API having "public" overrides, it seems to me most
consistent with the general aim of the proposal that open overrides should
be marked as such by the subclass's owner. The same logic that requires
explicit use of `open` for subclass declarations should require them for
overridden methods. (Whereas, clearly, inherited methods that don't show up
at all in the code inside the subclass are a different ballgame.)

···

On Sat, Jul 16, 2016 at 1:48 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sat, Jul 16, 2016 at 1:16 PM, John McCall via swift-evolution < > swift-evolution@swift.org> wrote:

On Jul 16, 2016, at 11:03 AM, T.J. Usiyan <griotspeak@gmail.com> wrote:

John.

On Sat, Jul 16, 2016 at 1:35 PM, John McCall <rjmccall@apple.com> wrote:

On Jul 16, 2016, at 9:32 AM, Matthew Johnson via swift-evolution < >>> swift-evolution@swift.org> wrote:
Sent from my iPhone

On Jul 16, 2016, at 10:59 AM, T.J. Usiyan via swift-evolution < >>> swift-evolution@swift.org> wrote:

Yes, sorry, my point was that this consideration isn't spelled out.

Another question is whether or not making a subclass of an open class
public by default is what we want. I see why it would be, I just think that
it is a wrinkle to default to internal otherwise but not here.

I can't think of any good reason to assume a specific class should be
public just because it is a subclass of an open class. The internal
default would still be the right default in this case.

Right, there's no new restriction here. Of course you can make a
private or internal subclass of a public open class — otherwise, you'd have
to publicize every subclass of (say) UIViewController.

John.

On Sat, Jul 16, 2016 at 10:32 AM, Karl <razielim@gmail.com> wrote:

> On 16 Jul 2016, at 16:10, T.J. Usiyan via swift-evolution < >>>> swift-evolution@swift.org> wrote:
>
> What happens if I want an `internal` subclass of an `open` class?

That should be allowable. You may want some optimised implementations,
similar to how Apple used class-clusters in Obj-C. I don’t think that same
pattern is exactly possible in Swift (I don’t think a class can set ‘self’
in its initialiser, or at least it couldn’t in Swift 1). But the same
principle applies - you may want a public class which you don’t allow
others to subclass, but you might have a static method or other function
which returns an internal optimised implementation.

If you used a protocol rather than a concrete type in that case,
theoretically others could conform to it and throw their own objects back
at your code, which goes against the point of this proposal.

We might think about creating ‘sealed’ protocols, too.

Karl

_______________________________________________
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 has always gone towards making declarations explicit to read. Having open on thé class declaration makes it so you don't have to go hunting into its members to see if it contains an open member.

Other comments inline:

2016/07/16 21:37、Jean-Daniel Dupas <mailing@xenonium.com> のメール:

2016/07/15 16:37、Riley Testut via swift-evolution <swift-evolution@swift.org> のメッセージ:

FWIW, I'm still against this proposal, but since it will be accepted regardless, here are my thoughts:

• Open keyword is significantly better.
• Members should be *open* by default, and final should be opt-in. If you're opening up a class for subclassing, my gut says you should allow the client to do as they wish.

If you have a class that was not open yet, just making it open wouldn't expose any members: it would then just be subclassable.

If the act of making the class open doesn't implicitly make overriding possible, well all you can do then is add methods, and that can be done with extensions anyways, so it's not as useful and makes the public open class {} pattern just by itself not so useful imho... :grimacing:

Also, the keyword 'open' itself may imply 'hey I'm open, please do what you want with my public members', whereas 'subclassable' is more specific in intention... (but that's just me, so n=1 and all that)

TLDR; +1 to the above: simpler is better and defaulting to overridable for public members on an open class is simpler... invariants can be protected by the 'final' keyword.

If we were to default to non-overridable, a more consistent 'open' on the method is preferred over overridable for me... open class, open method... much better imho...

Do we really need an open keyword ?

As already said, if open does nothing more than allowing the class to be subclassed, why not simply make the class subclassable if it contains at least one overridable member ?

Thats a good point actually… but looks like Review #2 has already started… and 'open' is available for both class and method there… I suppose its the whole "default to safe", just in case someone made one method 'open' they may not have intended to actually make the whole class open… (also see below)

In case we require an open keyword, what would happen if someone mark a member overridable, but does not make the class open ? Will the compiler emit an error, or make the class implicitly « open » ?

In proposal #2 looks like it would generate an error, but Xiaodi Wu has said that it should be allowed and not generate an error per SE-0025.
Take a look at: "The compiler should not warn when a broader level of access control is used within a type with more restrictive access, such as internal within a private type."

I'm fairly sure that does not apply to open as it's fairly orthogonal to other access control modifiers.

···

On 16 Jul 2016, at 14:49, Andre via swift-evolution <swift-evolution@swift.org> wrote:

Le 16 juil. 2016 à 00:31, Andre Elder via swift-evolution <swift-evolution@swift.org> a écrit :

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

That should be allowable. You may want some optimised implementations, similar to how Apple used class-clusters in Obj-C. I don’t think that same pattern is exactly possible in Swift (I don’t think a class can set ‘self’ in its initialiser, or at least it couldn’t in Swift 1). But the same principle applies - you may want a public class which you don’t allow others to subclass, but you might have a static method or other function which returns an internal optimised implementation.

If you used a protocol rather than a concrete type in that case, theoretically others could conform to it and throw their own objects back at your code, which goes against the point of this proposal.

We might think about creating ‘sealed’ protocols, too.

Karl

···

On 16 Jul 2016, at 16:10, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:

What happens if I want an `internal` subclass of an `open` class?

Sorry to mail 3 times in a row, but as I finished I remembered a concrete example of where sealed protocols would be helpful:

UIKit has a UITextInput protocol, which is used by custom text object which want to interact with the keyboard. It has a delegate property, of type UITextInputDelegate (another protocol).

I have seen lots of people try to have their own objects conform to UITextInputDelegate and set themselves as the delegate on a UITextInput object. That is the wrong usage of the property. You are never supposed to conform to UITextInputDelegate; the system has something which conforms to it, and it will set itself as your delegate at some point during text input. You use it to notify the system about changes to the text content and selection region.

If it was a sealed protocol, the UIKit API authors would be able to more clearly communicate this intention and people wouldn’t be able to fall in this trap. The only other way they could do it would be to use a concrete final type, which evidently they didn’t want to do (possibly because it has internal subclasses and can’t be final).

Karl

···

On 16 Jul 2016, at 16:32, Karl <raziel.im+swift-users@gmail.com> wrote:

On 16 Jul 2016, at 16:10, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:

What happens if I want an `internal` subclass of an `open` class?

That should be allowable. You may want some optimised implementations, similar to how Apple used class-clusters in Obj-C. I don’t think that same pattern is exactly possible in Swift (I don’t think a class can set ‘self’ in its initialiser, or at least it couldn’t in Swift 1). But the same principle applies - you may want a public class which you don’t allow others to subclass, but you might have a static method or other function which returns an internal optimised implementation.

If you used a protocol rather than a concrete type in that case, theoretically others could conform to it and throw their own objects back at your code, which goes against the point of this proposal.

We might think about creating ‘sealed’ protocols, too.

Karl

Makes sense. Thanks for clarifying.

···

On Sat, Jul 16, 2016 at 14:17 John McCall <rjmccall@apple.com> wrote:

On Jul 16, 2016, at 11:48 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
On Sat, Jul 16, 2016 at 1:16 PM, John McCall via swift-evolution < > swift-evolution@swift.org> wrote:

On Jul 16, 2016, at 11:03 AM, T.J. Usiyan <griotspeak@gmail.com> wrote:

"open is invalid on declarations that are not also public (see the
Alternatives discussion for rationale)."
+

"If an open class inherits an open method from a superclass, that method
remains open. If it overrides an open method from a superclass, the
override is implicitly open if it is not final."

I understand that the intent is probably not to say that subclasses are
public by default. My point is that those two statements, without an
explicit spelling out of the implicit access level, could lead me to
believe that subclasses are implicitly public by default. It is open to
interpretation. Neither the prose nor the code examples address it.

I see your general point. I'll think about how to re-word this; it may
be sufficient to just remove the requirement that open methods appear in
open classes. Suffice it for me to say now, officially, that this proposal
does not require classes to be public or open just because they override
open methods from an open superclass.

It might be barely sufficient solely to remove the requirement that open
methods appear in open classes. However, if my subclass is internal, I
shouldn't be required to declare a `public override` of an open method just
to satisfy the rules for `open`, which would be forced by the rule that
`open` is invalid on declarations that are not also `public`

This rule only applies to explicit uses of "open". A method that is
implicitly open due to overriding does not have this restriction.

In general, my intent in writing this proposal was to cover the important
interactions, not to write a fully precise specification. The general rule
about overrides having to be at least as accessible as the minimum of their
class and their overridden method still applies, superseded only by the
rule that it is acceptable to drop the "open" on a public open override.

combined with the rule that overrides of an open method are by default
open.

This would degrade the developer experience significantly, since a
beginning developer writing only internal subclasses for their own app
would now be required to litter either `public override` or `final
override` throughout their code in the ordinary course of subclassing. On
reconsideration, it might be best if overrides are not implicitly open.

I continue to think "override" is sufficient communication here. We're
not going to have a model where the inherited open API of the superclass
becomes non-open in the subclass. We don't want the mere existence of an
override in the subclass to change that because it's a fairly core goal
that the existence of an override (at least one which doesn't covariantly
refine the type) in a subclass should not affect source/binary
compatibility.

John.

John.

On Sat, Jul 16, 2016 at 1:35 PM, John McCall <rjmccall@apple.com> wrote:

On Jul 16, 2016, at 9:32 AM, Matthew Johnson via swift-evolution < >>> swift-evolution@swift.org> wrote:
Sent from my iPhone

On Jul 16, 2016, at 10:59 AM, T.J. Usiyan via swift-evolution < >>> swift-evolution@swift.org> wrote:

Yes, sorry, my point was that this consideration isn't spelled out.

Another question is whether or not making a subclass of an open class
public by default is what we want. I see why it would be, I just think that
it is a wrinkle to default to internal otherwise but not here.

I can't think of any good reason to assume a specific class should be
public just because it is a subclass of an open class. The internal
default would still be the right default in this case.

Right, there's no new restriction here. Of course you can make a
private or internal subclass of a public open class — otherwise, you'd have
to publicize every subclass of (say) UIViewController.

John.

On Sat, Jul 16, 2016 at 10:32 AM, Karl <razielim@gmail.com> wrote:

> On 16 Jul 2016, at 16:10, T.J. Usiyan via swift-evolution < >>>> swift-evolution@swift.org> wrote:
>
> What happens if I want an `internal` subclass of an `open` class?

That should be allowable. You may want some optimised implementations,
similar to how Apple used class-clusters in Obj-C. I don’t think that same
pattern is exactly possible in Swift (I don’t think a class can set ‘self’
in its initialiser, or at least it couldn’t in Swift 1). But the same
principle applies - you may want a public class which you don’t allow
others to subclass, but you might have a static method or other function
which returns an internal optimised implementation.

If you used a protocol rather than a concrete type in that case,
theoretically others could conform to it and throw their own objects back
at your code, which goes against the point of this proposal.

We might think about creating ‘sealed’ protocols, too.

Karl

_______________________________________________
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 think there is at least one legitimate case where you'd still want to implement these kinds of protocols: when you're writing unit tests and you want to create a mock delegate to verify that your code calls the delegate methods correctly.

Also, interface inheritance is much less dangerous than implementation inheritance; I can't think of a case where allowing external code to implement a protocol could lead to maintenance problems for the framework author like subclassing does. (Although I agree the user confusion that you described occurs a lot.)

Karoly
@lorentey

···

On 2016. Jul 16., at 16:45, Karl via swift-evolution <swift-evolution@swift.org> wrote:
Sorry to mail 3 times in a row, but as I finished I remembered a concrete example of where sealed protocols would be helpful:

UIKit has a UITextInput protocol, which is used by custom text object which want to interact with the keyboard. It has a delegate property, of type UITextInputDelegate (another protocol).

I have seen lots of people try to have their own objects conform to UITextInputDelegate and set themselves as the delegate on a UITextInput object. That is the wrong usage of the property. You are never supposed to conform to UITextInputDelegate; the system has something which conforms to it, and it will set itself as your delegate at some point during text input. You use it to notify the system about changes to the text content and selection region.

UITextInputDelegate | Apple Developer Documentation

If it was a sealed protocol, the UIKit API authors would be able to more clearly communicate this intention and people wouldn’t be able to fall in this trap. The only other way they could do it would be to use a concrete final type, which evidently they didn’t want to do (possibly because it has internal subclasses and can’t be final).

Regards
(From mobile)

"open is invalid on declarations that are not also public (see the Alternatives discussion for rationale)."

+

"If an open class inherits an open method from a superclass, that method remains open. If it overrides an open method from a superclass, the override is implicitly open if it is not final."

I understand that the intent is probably not to say that subclasses are public by default. My point is that those two statements, without an explicit spelling out of the implicit access level, could lead me to believe that subclasses are implicitly public by default. It is open to interpretation. Neither the prose nor the code examples address it.

I see your general point. I'll think about how to re-word this; it may be sufficient to just remove the requirement that open methods appear in open classes. Suffice it for me to say now, officially, that this proposal does not require classes to be public or open just because they override open methods from an open superclass.

It might be barely sufficient solely to remove the requirement that open methods appear in open classes. However, if my subclass is internal, I shouldn't be required to declare a `public override` of an open method just to satisfy the rules for `open`, which would be forced by the rule that `open` is invalid on declarations that are not also `public`

This rule only applies to explicit uses of "open". A method that is implicitly open due to overriding does not have this restriction.

In general, my intent in writing this proposal was to cover the important interactions, not to write a fully precise specification. The general rule about overrides having to be at least as accessible as the minimum of their class and their overridden method still applies, superseded only by the rule that it is acceptable to drop the "open" on a public open override.

combined with the rule that overrides of an open method are by default open.

This would degrade the developer experience significantly, since a beginning developer writing only internal subclasses for their own app would now be required to litter either `public override` or `final override` throughout their code in the ordinary course of subclassing. On reconsideration, it might be best if overrides are not implicitly open.

I continue to think "override" is sufficient communication here. We're not going to have a model where the inherited open API of the superclass becomes non-open in the subclass.

the logic of the proposal would dictate that it did: by subclasing the original type into a new type, the programmer is effectively removing any of the original guaranties that the first programmer made about how cohesively all paths into the type operated. The new code defines a new outer boundary for the subtype that has every reason not to be trusted by default to be working for subclasing, for the same reasons the original types could not be implicitely trusted either.

···

On Jul 16, 2016, at 9:17 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Jul 16, 2016, at 11:48 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
On Sat, Jul 16, 2016 at 1:16 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Jul 16, 2016, at 11:03 AM, T.J. Usiyan <griotspeak@gmail.com> wrote:

We don't want the mere existence of an override in the subclass to change that because it's a fairly core goal that the existence of an override (at least one which doesn't covariantly refine the type) in a subclass should not affect source/binary compatibility.

John.

John.

On Sat, Jul 16, 2016 at 1:35 PM, John McCall <rjmccall@apple.com> wrote:

On Jul 16, 2016, at 9:32 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:
Sent from my iPhone

On Jul 16, 2016, at 10:59 AM, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:

Yes, sorry, my point was that this consideration isn't spelled out.

Another question is whether or not making a subclass of an open class public by default is what we want. I see why it would be, I just think that it is a wrinkle to default to internal otherwise but not here.

I can't think of any good reason to assume a specific class should be public just because it is a subclass of an open class. The internal default would still be the right default in this case.

Right, there's no new restriction here. Of course you can make a private or internal subclass of a public open class — otherwise, you'd have to publicize every subclass of (say) UIViewController.

John.

On Sat, Jul 16, 2016 at 10:32 AM, Karl <razielim@gmail.com> wrote:

> On 16 Jul 2016, at 16:10, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:
>
> What happens if I want an `internal` subclass of an `open` class?

That should be allowable. You may want some optimised implementations, similar to how Apple used class-clusters in Obj-C. I don’t think that same pattern is exactly possible in Swift (I don’t think a class can set ‘self’ in its initialiser, or at least it couldn’t in Swift 1). But the same principle applies - you may want a public class which you don’t allow others to subclass, but you might have a static method or other function which returns an internal optimised implementation.

If you used a protocol rather than a concrete type in that case, theoretically others could conform to it and throw their own objects back at your code, which goes against the point of this proposal.

We might think about creating ‘sealed’ protocols, too.

Karl

_______________________________________________
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