[Proposal Draft] Remove open Access Modifier


(Dimitri Racordon) #1

Hi all,

Here’s a draft proposal following https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032576.html. The idea is simplify Swift’s syntax by getting rid of the `open` access modifier.

A rendered version of the proposal is available here: https://github.com/kyouko-taiga/swift-evolution/blob/master/proposals/nnnn-remove-open-access-modifier.md
The raw version follows:

# Remove open Access Modifier

* Proposal: [SE-NNNN](nnnn-remove-open-access-modifier.md)
* Author: [Dimitri Racordon](https://github.com/kyouko-taiga), Joanna Carter
* Status: **Awaiting review**
* Review manager: TBD

## Introduction

Swift allows classes, methods, properties and subscripts to be marked as `final`, hence disallowing their subclassing/overriding inside **and** outside of their defining module.

It also features two access levels `open`, which allows an entity to be accessed outside its defining module, and `public`, which gives the same access level the former **and** allows the entity to be subclassed/overridden.

There's a clear overlap between `open` and `public`, as they essentially represent the same access control within the boundaries of a module, and do not add any benefit from outside them, as `final` is sufficient to prohibit subclassing/overriding.

Swift-evolution thread: ['Public' class visibility specifiers](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032576.html)

## Motivation

Swift has currently 5 access levels, in the form of:

* `private`, restricting the use of an entity to its enclosing declaration;
* `fileprivate`, restricting the use of an entity to its defining source file:
* `internal`, restricting the use of an entity to its defining module;
* `public`, allowing the entity to be accessed anywhere;
* `open`, allowing the entity to be accessed anywhere **and** allowing the entity to be subclassed/overridden outside of their defining module.

From inside a module, `open` and `public` represent exactly the same access level (everything is visible **and** can be subclassed/overridden).
From outside a module, `public` is actually akin to `final`.

// Module 1
// ========

open class OpenClass {}
public class PublicClass {}

public final class PublicFinalClass {}

// The first two classes above have the same access level.
class derivedFromOpen: OpenClass {}
class derivedFromPublic: PublicClass {}

// Module 2
// ========

class derivedFromOpenOutside: OpenClass {}

class derivedFromPublicOutside: PublicClass {}
// Error: Cannot inherit from non-open class ...

class derivedFromPublicFinalOutside: PublicFinalClass {}
// Error: Inheritance from a final class ...

Hence, the sole use-case of using both `public` and `final` is for an entity that *inside* its defining module should not be subclassed/overridden.

// Module 1
// ========

class derivedFromPublicFinal : PublicFinalClass {}
// Error: Inheritance from a final class ...

We believe this use case is rare and not worth the additional complexity of having an `open` access level in the language.
Besides, `open` is only applicable on classes and class members while the others can be used on other entities (protocols, structures, ...).
This asymmetry adds to the complexity of an `open` access level.

In order to simplify the syntax of Swift, we propose to **remove the `open` access modifier**.

## Proposal

Remove the `open` access modifier from Swift.

## Source compatibility

This is a breaking change, as the `open` keyword would disappear from the language.
However, a fixit would be quite easy to put in place, simply replacing `open` with `public`.

## Alternative considered

Not removing the `open` access modifier from the language and keep the status quo.


(Brent Royal-Gordon) #2

Really? Three sentences presenting an unsupported opinion?

SE-0117[1], which proposed the `open` access modifier, spent approximately 1,080 words explaining why adding `open` was a good idea. If you are serious about removing `open`, I would strongly suggest you read that explanation and prepare a similarly well-reasoned and well-supported explanation of why you think removing `open` is a good idea.

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

···

On Feb 20, 2017, at 10:44 PM, Dimitri Racordon via swift-evolution <swift-evolution@swift.org> wrote:

We believe this use case is rare and not worth the additional complexity of having an `open` access level in the language.
Besides, `open` is only applicable on classes and class members while the others can be used on other entities (protocols, structures, ...).
This asymmetry adds to the complexity of an `open` access level.

--
Brent Royal-Gordon
Architechies


(David Hart) #3

I think this proposal will receive a lot of pushback and that the use case for having a class that is subclassable inside its module but not subclassable outside the module is more frequent than you think.

···

On 21 Feb 2017, at 07:44, Dimitri Racordon via swift-evolution <swift-evolution@swift.org> wrote:

Hi all,

Here’s a draft proposal following https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032576.html.
The idea is simplify Swift’s syntax by getting rid of the `open` access modifier.

A rendered version of the proposal is available here: https://github.com/kyouko-taiga/swift-evolution/blob/master/proposals/nnnn-remove-open-access-modifier.md
The raw version follows:

# Remove open Access Modifier

* Proposal: [SE-NNNN](nnnn-remove-open-access-modifier.md)
* Author: [Dimitri Racordon](https://github.com/kyouko-taiga), Joanna Carter
* Status: **Awaiting review**
* Review manager: TBD

## Introduction

Swift allows classes, methods, properties and subscripts to be marked as `final`, hence disallowing their subclassing/overriding inside **and** outside of their defining module.

It also features two access levels `open`, which allows an entity to be accessed outside its defining module, and `public`, which gives the same access level the former **and** allows the entity to be subclassed/overridden.

There's a clear overlap between `open` and `public`, as they essentially represent the same access control within the boundaries of a module, and do not add any benefit from outside them, as `final` is sufficient to prohibit subclassing/overriding.

Swift-evolution thread: ['Public' class visibility specifiers](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032576.html)

## Motivation

Swift has currently 5 access levels, in the form of:

* `private`, restricting the use of an entity to its enclosing declaration;
* `fileprivate`, restricting the use of an entity to its defining source file:
* `internal`, restricting the use of an entity to its defining module;
* `public`, allowing the entity to be accessed anywhere;
* `open`, allowing the entity to be accessed anywhere **and** allowing the entity to be subclassed/overridden outside of their defining module.

From inside a module, `open` and `public` represent exactly the same access level (everything is visible **and** can be subclassed/overridden).
From outside a module, `public` is actually akin to `final`.

// Module 1
// ========

open class OpenClass {}
public class PublicClass {}

public final class PublicFinalClass {}

// The first two classes above have the same access level.
class derivedFromOpen: OpenClass {}
class derivedFromPublic: PublicClass {}

// Module 2
// ========

class derivedFromOpenOutside: OpenClass {}

class derivedFromPublicOutside: PublicClass {}
// Error: Cannot inherit from non-open class ...

class derivedFromPublicFinalOutside: PublicFinalClass {}
// Error: Inheritance from a final class ...

Hence, the sole use-case of using both `public` and `final` is for an entity that *inside* its defining module should not be subclassed/overridden.

// Module 1
// ========

class derivedFromPublicFinal : PublicFinalClass {}
// Error: Inheritance from a final class ...

We believe this use case is rare and not worth the additional complexity of having an `open` access level in the language.
Besides, `open` is only applicable on classes and class members while the others can be used on other entities (protocols, structures, ...).
This asymmetry adds to the complexity of an `open` access level.

In order to simplify the syntax of Swift, we propose to **remove the `open` access modifier**.

## Proposal

Remove the `open` access modifier from Swift.

## Source compatibility

This is a breaking change, as the `open` keyword would disappear from the language.
However, a fixit would be quite easy to put in place, simply replacing `open` with `public`.

## Alternative considered

Not removing the `open` access modifier from the language and keep the status quo.

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


(Rien) #4

While I am in favor of this, I do think this should not be a proposal on its own, rather it should be folded into a general overhaul of the entire access level structure.

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Balancingrock
Project: http://swiftfire.nl

···

On 21 Feb 2017, at 07:44, Dimitri Racordon via swift-evolution <swift-evolution@swift.org> wrote:

Hi all,

Here’s a draft proposal following https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032576.html
.

The idea is simplify Swift’s syntax by getting rid of the `open` access modifier.

A rendered version of the proposal is available here: https://github.com/kyouko-taiga/swift-evolution/blob/master/proposals/nnnn-remove-open-access-modifier.md
The raw version follows:

# Remove open Access Modifier

* Proposal: [SE-NNNN](nnnn-remove-open-access-modifier.md)
* Author: [Dimitri Racordon](
https://github.com/kyouko-taiga
), Joanna Carter
* Status: **Awaiting review**
* Review manager: TBD

## Introduction

Swift allows classes, methods, properties and subscripts to be marked as `final`, hence disallowing their subclassing/overriding inside **and** outside of their defining module.

It also features two access levels `open`, which allows an entity to be accessed outside its defining module, and `public`, which gives the same access level the former **and** allows the entity to be subclassed/overridden.

There's a clear overlap between `open` and `public`, as they essentially represent the same access control within the boundaries of a module, and do not add any benefit from outside them, as `final` is sufficient to prohibit subclassing/overriding.

Swift-evolution thread: ['Public' class visibility specifiers](
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032576.html
)

## Motivation

Swift has currently 5 access levels, in the form of:

* `private`, restricting the use of an entity to its enclosing declaration;
* `fileprivate`, restricting the use of an entity to its defining source file:
* `internal`, restricting the use of an entity to its defining module;
* `public`, allowing the entity to be accessed anywhere;
* `open`, allowing the entity to be accessed anywhere **and** allowing the entity to be subclassed/overridden outside of their defining module.

From inside a module, `open` and `public` represent exactly the same access level (everything is visible **and** can be subclassed/overridden).
From outside a module, `public` is actually akin to `final`.

// Module 1
// ========

open class OpenClass {}
public class PublicClass {}

public final class PublicFinalClass {}

// The first two classes above have the same access level.
class derivedFromOpen: OpenClass {}
class derivedFromPublic: PublicClass {}

// Module 2
// ========

class derivedFromOpenOutside: OpenClass {}

class derivedFromPublicOutside: PublicClass {}
// Error: Cannot inherit from non-open class ...

class derivedFromPublicFinalOutside: PublicFinalClass {}
// Error: Inheritance from a final class ...

Hence, the sole use-case of using both `public` and `final` is for an entity that *inside* its defining module should not be subclassed/overridden.

// Module 1
// ========

class derivedFromPublicFinal : PublicFinalClass {}
// Error: Inheritance from a final class ...

We believe this use case is rare and not worth the additional complexity of having an `open` access level in the language.
Besides, `open` is only applicable on classes and class members while the others can be used on other entities (protocols, structures, ...).
This asymmetry adds to the complexity of an `open` access level.

In order to simplify the syntax of Swift, we propose to **remove the `open` access modifier**.

## Proposal

Remove the `open` access modifier from Swift.

## Source compatibility

This is a breaking change, as the `open` keyword would disappear from the language.
However, a fixit would be quite easy to put in place, simply replacing `open` with `public`.

## Alternative considered

Not removing the `open` access modifier from the language and keep the status quo.

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


(Dimitri Racordon) #5

Really? Three sentences presenting an unsupported opinion?

I’ll concede that the proposal makes a claim that might very well be disproved. I would very much like to see an actual example of a public class that **has** to be public but **shouldn’t** be open for obvious reasons. I would happily accept being shown wrong on that point.

Besides, I don’t claim this use-case never happens, but only that it is not so common. Although, this remark wasn’t included in the proposal, I also claim that for those instances, the risk involved is generally be acceptable. To some extent, this opinion is also shared in SE-0117:

“Within a single module, this can be tolerable, but across library boundaries it's very problematic unless the superclass has established firm rules from the beginning.”

The idea is to say that if the use-case is rare (once again, I’d accept being shown wrong here) and the problems it involves are tolerable, then the added complexity induced by an additional access level and its keyword is not worth it.

Like SE-0117, I too advocate that “designing a class well for subclassing takes far more effort than just designing it for ordinary use”. My belief however is that `open` doesn't fixes this issue. Instead, it hinders considering marking an entity `final`, as one may think that `public` is safe enough. In addition, the role of `final` for public entities becomes unclear for the library user, as anything not marked `open` can be understood as `final` anyway.

The asymmetry induced by `open` in the language is a fact. As stated by the documentation: “Open access applies only to classes and class member”. I’d be tempting to say that asymmetry in any system adds complexity to the said system. To the very least, it makes the asymmetry an exception to know about.

···

On 21 Feb 2017, at 13:19, Brent Royal-Gordon <brent@architechies.com<mailto:brent@architechies.com>> wrote:


(Chris Lattner) #6

This is a source breaking change that needs extreme justification. Since the (extensive) discussion that introduced ‘open’ in Swift 3, I haven’t heard of practical problems with it, so I see little to no chance of this proposal going anywhere.

-Chris

···

On Feb 20, 2017, at 10:44 PM, Dimitri Racordon via swift-evolution <swift-evolution@swift.org> wrote:

Hi all,

Here’s a draft proposal following https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032576.html.
The idea is simplify Swift’s syntax by getting rid of the `open` access modifier.


(Dimitri Racordon) #7

Hi David,

Thanks for your feedback.
Do you have yourself an example in which a final entity would be clearly needed inside its module?

I have seen theoretical use-cases already, but haven’t encountered a “real-life” situation that’d need this pattern yet.

···

On 21 Feb 2017, at 08:02, David Hart <david@hartbit.com<mailto:david@hartbit.com>> wrote:

I think this proposal will receive a lot of pushback and that the use case for having a class that is subclassable inside its module but not subclassable outside the module is more frequent than you think.

On 21 Feb 2017, at 07:44, Dimitri Racordon via swift-evolution <swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

Hi all,

Here’s a draft proposal following https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032576.html. The idea is simplify Swift’s syntax by getting rid of the `open` access modifier.

A rendered version of the proposal is available here: https://github.com/kyouko-taiga/swift-evolution/blob/master/proposals/nnnn-remove-open-access-modifier.md
The raw version follows:

# Remove open Access Modifier

* Proposal: [SE-NNNN](nnnn-remove-open-access-modifier.md)
* Author: [Dimitri Racordon](https://github.com/kyouko-taiga), Joanna Carter
* Status: **Awaiting review**
* Review manager: TBD

## Introduction

Swift allows classes, methods, properties and subscripts to be marked as `final`, hence disallowing their subclassing/overriding inside **and** outside of their defining module.

It also features two access levels `open`, which allows an entity to be accessed outside its defining module, and `public`, which gives the same access level the former **and** allows the entity to be subclassed/overridden.

There's a clear overlap between `open` and `public`, as they essentially represent the same access control within the boundaries of a module, and do not add any benefit from outside them, as `final` is sufficient to prohibit subclassing/overriding.

Swift-evolution thread: ['Public' class visibility specifiers](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032576.html)

## Motivation

Swift has currently 5 access levels, in the form of:

* `private`, restricting the use of an entity to its enclosing declaration;
* `fileprivate`, restricting the use of an entity to its defining source file:
* `internal`, restricting the use of an entity to its defining module;
* `public`, allowing the entity to be accessed anywhere;
* `open`, allowing the entity to be accessed anywhere **and** allowing the entity to be subclassed/overridden outside of their defining module.

From inside a module, `open` and `public` represent exactly the same access level (everything is visible **and** can be subclassed/overridden).
From outside a module, `public` is actually akin to `final`.

// Module 1
// ========

open class OpenClass {}
public class PublicClass {}

public final class PublicFinalClass {}

// The first two classes above have the same access level.
class derivedFromOpen: OpenClass {}
class derivedFromPublic: PublicClass {}

// Module 2
// ========

class derivedFromOpenOutside: OpenClass {}

class derivedFromPublicOutside: PublicClass {}
// Error: Cannot inherit from non-open class ...

class derivedFromPublicFinalOutside: PublicFinalClass {}
// Error: Inheritance from a final class ...

Hence, the sole use-case of using both `public` and `final` is for an entity that *inside* its defining module should not be subclassed/overridden.

// Module 1
// ========

class derivedFromPublicFinal : PublicFinalClass {}
// Error: Inheritance from a final class ...

We believe this use case is rare and not worth the additional complexity of having an `open` access level in the language.
Besides, `open` is only applicable on classes and class members while the others can be used on other entities (protocols, structures, ...).
This asymmetry adds to the complexity of an `open` access level.

In order to simplify the syntax of Swift, we propose to **remove the `open` access modifier**.

## Proposal

Remove the `open` access modifier from Swift.

## Source compatibility

This is a breaking change, as the `open` keyword would disappear from the language.
However, a fixit would be quite easy to put in place, simply replacing `open` with `public`.

## Alternative considered

Not removing the `open` access modifier from the language and keep the status quo.

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


(Goffredo Marocchi) #8

To those people I would say use final or let's change public to mean the current open and replace open with 'module'...

I liked open by default and this not needing open in the first place... you guys got me here ;).

···

Sent from my iPhone

On 21 Feb 2017, at 07:02, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

I think this proposal will receive a lot of pushback and that the use case for having a class that is subclassable inside its module but not subclassable outside the module is more frequent than you think.

On 21 Feb 2017, at 07:44, Dimitri Racordon via swift-evolution <swift-evolution@swift.org> wrote:

Hi all,

Here’s a draft proposal following https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032576.html.
The idea is simplify Swift’s syntax by getting rid of the `open` access modifier.

A rendered version of the proposal is available here: https://github.com/kyouko-taiga/swift-evolution/blob/master/proposals/nnnn-remove-open-access-modifier.md
The raw version follows:

# Remove open Access Modifier

* Proposal: [SE-NNNN](nnnn-remove-open-access-modifier.md)
* Author: [Dimitri Racordon](https://github.com/kyouko-taiga), Joanna Carter
* Status: **Awaiting review**
* Review manager: TBD

## Introduction

Swift allows classes, methods, properties and subscripts to be marked as `final`, hence disallowing their subclassing/overriding inside **and** outside of their defining module.

It also features two access levels `open`, which allows an entity to be accessed outside its defining module, and `public`, which gives the same access level the former **and** allows the entity to be subclassed/overridden.

There's a clear overlap between `open` and `public`, as they essentially represent the same access control within the boundaries of a module, and do not add any benefit from outside them, as `final` is sufficient to prohibit subclassing/overriding.

Swift-evolution thread: ['Public' class visibility specifiers](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032576.html)

## Motivation

Swift has currently 5 access levels, in the form of:

* `private`, restricting the use of an entity to its enclosing declaration;
* `fileprivate`, restricting the use of an entity to its defining source file:
* `internal`, restricting the use of an entity to its defining module;
* `public`, allowing the entity to be accessed anywhere;
* `open`, allowing the entity to be accessed anywhere **and** allowing the entity to be subclassed/overridden outside of their defining module.

From inside a module, `open` and `public` represent exactly the same access level (everything is visible **and** can be subclassed/overridden).
From outside a module, `public` is actually akin to `final`.

// Module 1
// ========

open class OpenClass {}
public class PublicClass {}

public final class PublicFinalClass {}

// The first two classes above have the same access level.
class derivedFromOpen: OpenClass {}
class derivedFromPublic: PublicClass {}

// Module 2
// ========

class derivedFromOpenOutside: OpenClass {}

class derivedFromPublicOutside: PublicClass {}
// Error: Cannot inherit from non-open class ...

class derivedFromPublicFinalOutside: PublicFinalClass {}
// Error: Inheritance from a final class ...

Hence, the sole use-case of using both `public` and `final` is for an entity that *inside* its defining module should not be subclassed/overridden.

// Module 1
// ========

class derivedFromPublicFinal : PublicFinalClass {}
// Error: Inheritance from a final class ...

We believe this use case is rare and not worth the additional complexity of having an `open` access level in the language.
Besides, `open` is only applicable on classes and class members while the others can be used on other entities (protocols, structures, ...).
This asymmetry adds to the complexity of an `open` access level.

In order to simplify the syntax of Swift, we propose to **remove the `open` access modifier**.

## Proposal

Remove the `open` access modifier from Swift.

## Source compatibility

This is a breaking change, as the `open` keyword would disappear from the language.
However, a fixit would be quite easy to put in place, simply replacing `open` with `public`.

## Alternative considered

Not removing the `open` access modifier from the language and keep the status quo.

_______________________________________________
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


(Tino) #9

I’ll concede that the proposal makes a claim that might very well be disproved. I would very much like to see an actual example of a public class that **has** to be public but **shouldn’t** be open for obvious reasons. I would happily accept being shown wrong on that point.

This is afaics one of the most active disputes on evolution — and you can save you a lot of grief by accepting that it is pointless:
The whole discussion isn't based on facts at all, despite many false claims that marking things as final is generally better.
I have asked for a single example to prove this in the past as well, so I guess no one can present such a thing to you.

It is personal preference, so arguments don't help much here.

Maybe it helps to know the whole story, as everything started with "final should be default", followed by a try to forbid subclassing for types from a different module by default, finally arriving at the current compromise where you have to decide wether module clients should be allowed to subclass or not.
Nobody ever requested that public should be the only access level, so there has been only been pressure applied from one direction — it's interesting to see some backlash now.
Imho people already were quite tired of discussion when public/open was accepted as a compromise...


(Jean-Daniel) #10

I’ll concede that the proposal makes a claim that might very well be disproved. I would very much like to see an actual example of a public class that **has** to be public but **shouldn’t** be open for obvious reasons. I would happily accept being shown wrong on that point.

This is afaics one of the most active disputes on evolution — and you can save you a lot of grief by accepting that it is pointless:
The whole discussion isn't based on facts at all, despite many false claims that marking things as final is generally better.
I have asked for a single example to prove this in the past as well, so I guess no one can present such a thing to you.

This is bad faith. The original discussion contains many real life example. You just don’t want to admit open is useful for many library writers.

···

Le 21 févr. 2017 à 17:19, Tino Heth via swift-evolution <swift-evolution@swift.org> a écrit :

It is personal preference, so arguments don't help much here.

Maybe it helps to know the whole story, as everything started with "final should be default", followed by a try to forbid subclassing for types from a different module by default, finally arriving at the current compromise where you have to decide wether module clients should be allowed to subclass or not.
Nobody ever requested that public should be the only access level, so there has been only been pressure applied from one direction — it's interesting to see some backlash now.
Imho people already were quite tired of discussion when public/open was accepted as a compromise...
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Charlie Monroe) #11

I’ll concede that the proposal makes a claim that might very well be disproved. I would very much like to see an actual example of a public class that **has** to be public but **shouldn’t** be open for obvious reasons. I would happily accept being shown wrong on that point.

This is afaics one of the most active disputes on evolution — and you can save you a lot of grief by accepting that it is pointless:
The whole discussion isn't based on facts at all, despite many false claims that marking things as final is generally better.
I have asked for a single example to prove this in the past as well, so I guess no one can present such a thing to you.

To me, the largest purpose is when you have a root class ("abstract") and a few subclasses that represent various options - in Scala, this would be a case class. For various reasons, it can't be an enum - for example, you need a lot of stored data and an enum case a(Int, Int, Int, Bool, Int, Double) is not very usable.

In certain places, you can have switches based on the actual subtype - with the default case causing fatalError. In such case, you definitely don't want additional subclasses to exist outside of the module as it would break the assumption of a known number of subclasses.

You can't make the root class final since you inherit from it. In such case, the public modifier makes sense.

···

On Feb 22, 2017, at 8:15 AM, Jean-Daniel via swift-evolution <swift-evolution@swift.org> wrote:

Le 21 févr. 2017 à 17:19, Tino Heth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

This is bad faith. The original discussion contains many real life example. You just don’t want to admit open is useful for many library writers.

It is personal preference, so arguments don't help much here.

Maybe it helps to know the whole story, as everything started with "final should be default", followed by a try to forbid subclassing for types from a different module by default, finally arriving at the current compromise where you have to decide wether module clients should be allowed to subclass or not.
Nobody ever requested that public should be the only access level, so there has been only been pressure applied from one direction — it's interesting to see some backlash now.
Imho people already were quite tired of discussion when public/open was accepted as a compromise...
_______________________________________________
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
https://lists.swift.org/mailman/listinfo/swift-evolution


(Goffredo Marocchi) #12

Maybe some people disagree with the emphasis on the library writer POV and from a user perspective of other people's libraries they have been accustomed to how you can be trusted with enough responsibility to either fix a behaviour in the binary lib you have been given or modify the sequence of some events for user flow reasons. Let's not act like a lot of people did never benefit from method swizzling at runtime (quite often it is popular libraries we use that do that for us, but it can be an invaluable tool as many other features of the Objective-C runtime... there is a reason why UI programming and rapid prototyping are massively more enjoyable in more dynamic languages like JavaScript, ruby, and Objective-C).

···

Sent from my iPhone

On 22 Feb 2017, at 07:15, Jean-Daniel via swift-evolution <swift-evolution@swift.org> wrote:

Le 21 févr. 2017 à 17:19, Tino Heth via swift-evolution <swift-evolution@swift.org> a écrit :

I’ll concede that the proposal makes a claim that might very well be disproved. I would very much like to see an actual example of a public class that **has** to be public but **shouldn’t** be open for obvious reasons. I would happily accept being shown wrong on that point.

This is afaics one of the most active disputes on evolution — and you can save you a lot of grief by accepting that it is pointless:
The whole discussion isn't based on facts at all, despite many false claims that marking things as final is generally better.
I have asked for a single example to prove this in the past as well, so I guess no one can present such a thing to you.

This is bad faith. The original discussion contains many real life example. You just don’t want to admit open is useful for many library writers.

It is personal preference, so arguments don't help much here.

Maybe it helps to know the whole story, as everything started with "final should be default", followed by a try to forbid subclassing for types from a different module by default, finally arriving at the current compromise where you have to decide wether module clients should be allowed to subclass or not.
Nobody ever requested that public should be the only access level, so there has been only been pressure applied from one direction — it's interesting to see some backlash now.
Imho people already were quite tired of discussion when public/open was accepted as a compromise...
_______________________________________________
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


(Tino) #13

This is bad faith. The original discussion contains many real life example.

"bad faith"? Really? If we have the same interpretation of this phrase in our dictionaries, it's only fitting here as attribute for the sentence following it.
I took a position that is extremely easy to attack, yet the only counter argument is the claim that there are many real life examples (instead of citing a single one). That's just "alternative facts", and it tells a lot about the actual power of the arguments that are used to justify forbidding subclassing.
Afaik, there hasn't been a single real life example by those who fought for "final by default", and it took quite a long time until someone from core came up with a scenario which illustrated a disadvantage of non-final classes in a lib — but that example had bad (worse) consequences in a final-by-default setup as well, so it wasn't convincing for me.

First step in discussion should be agreeing on facts, and in this discussion, imho the most important fact is that this actually isn't about facts at all, but rather about opinion and personal preferences:
When someone suggests to rename the keyword "func" to "fn" or "function", it is ridiculous to argue that either choice is better, and the same is true for this topic (it just has bigger consequences).
When you actually read the original discussion, I expect you will find more false claims and questionable tactics from both parties than valuable examples, and this drags down the quality of the debate.

You just don’t want to admit open is useful for many library writers.

Of course open is extremely useful for library writers — especially for those who write libraries that are intended to be actually used…
Did anyone question that? (I guess the title of the thread can be a little bit irritating, but afaics, it is only the keyword that should be removed, not the feature itself).

As I told the author of this draft, I can only tell its opposers as well:
Just relax and admit that you are not fighting for the better choice, but only for the one you like better.

(btw, that is the case for a lot of decisions:
Typed throws aren't better than untyped ones, zero-based arrays aren't better than 1-based arrays, functional programming isn't better than POP or OO, composition isn't better than inheritance, structs aren't better than classes… the strongest statement you can make for some of those alternatives is that they perform better in specific situations)


(Jon Hull) #14

What I have done for this case is have a protocol with several private conforming Structs, and then wrap it all in a public final class which wraps a boxed instance of one of the conformers.

Here is some code: https://gist.github.com/jonhull/b9cd8a50abca16ea49eade2c91edf8a2

In this case, I chose to keep the protocol and associated init public so it could be extended… but they could have just as easily been private. The need for the type erasure hack should disappear with updated generics...

Thanks,
Jon

···

On Feb 21, 2017, at 11:29 PM, Charlie Monroe via swift-evolution <swift-evolution@swift.org> wrote:

On Feb 22, 2017, at 8:15 AM, Jean-Daniel via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Le 21 févr. 2017 à 17:19, Tino Heth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

I’ll concede that the proposal makes a claim that might very well be disproved. I would very much like to see an actual example of a public class that **has** to be public but **shouldn’t** be open for obvious reasons. I would happily accept being shown wrong on that point.

This is afaics one of the most active disputes on evolution — and you can save you a lot of grief by accepting that it is pointless:
The whole discussion isn't based on facts at all, despite many false claims that marking things as final is generally better.
I have asked for a single example to prove this in the past as well, so I guess no one can present such a thing to you.

To me, the largest purpose is when you have a root class ("abstract") and a few subclasses that represent various options - in Scala, this would be a case class. For various reasons, it can't be an enum - for example, you need a lot of stored data and an enum case a(Int, Int, Int, Bool, Int, Double) is not very usable.


(Charlie Monroe) #15

I’ll concede that the proposal makes a claim that might very well be disproved. I would very much like to see an actual example of a public class that **has** to be public but **shouldn’t** be open for obvious reasons. I would happily accept being shown wrong on that point.

This is afaics one of the most active disputes on evolution — and you can save you a lot of grief by accepting that it is pointless:
The whole discussion isn't based on facts at all, despite many false claims that marking things as final is generally better.
I have asked for a single example to prove this in the past as well, so I guess no one can present such a thing to you.

To me, the largest purpose is when you have a root class ("abstract") and a few subclasses that represent various options - in Scala, this would be a case class. For various reasons, it can't be an enum - for example, you need a lot of stored data and an enum case a(Int, Int, Int, Bool, Int, Double) is not very usable.

What I have done for this case is have a protocol with several private conforming Structs, and then wrap it all in a public final class which wraps a boxed instance of one of the conformers.

It's not always possible to flatten it down to structs, sometimes you do need the class hierarchy and inheritance. ObjC support is one of the reasons, others are purely based on the need for inheritance.

···

On Feb 22, 2017, at 10:35 AM, Jonathan Hull <jhull@gbis.com> wrote:

On Feb 21, 2017, at 11:29 PM, Charlie Monroe via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Feb 22, 2017, at 8:15 AM, Jean-Daniel via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Le 21 févr. 2017 à 17:19, Tino Heth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Here is some code: https://gist.github.com/jonhull/b9cd8a50abca16ea49eade2c91edf8a2

In this case, I chose to keep the protocol and associated init public so it could be extended… but they could have just as easily been private. The need for the type erasure hack should disappear with updated generics...

Thanks,
Jon


(Goffredo Marocchi) #16

Well said, thanks for taking time to post this :).

···

Sent from my iPhone

On 22 Feb 2017, at 19:34, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

This is bad faith. The original discussion contains many real life example.

"bad faith"? Really? If we have the same interpretation of this phrase in our dictionaries, it's only fitting here as attribute for the sentence following it.
I took a position that is extremely easy to attack, yet the only counter argument is the claim that there are many real life examples (instead of citing a single one). That's just "alternative facts", and it tells a lot about the actual power of the arguments that are used to justify forbidding subclassing.
Afaik, there hasn't been a single real life example by those who fought for "final by default", and it took quite a long time until someone from core came up with a scenario which illustrated a disadvantage of non-final classes in a lib — but that example had bad (worse) consequences in a final-by-default setup as well, so it wasn't convincing for me.

First step in discussion should be agreeing on facts, and in this discussion, imho the most important fact is that this actually isn't about facts at all, but rather about opinion and personal preferences:
When someone suggests to rename the keyword "func" to "fn" or "function", it is ridiculous to argue that either choice is better, and the same is true for this topic (it just has bigger consequences).
When you actually read the original discussion, I expect you will find more false claims and questionable tactics from both parties than valuable examples, and this drags down the quality of the debate.

You just don’t want to admit open is useful for many library writers.

Of course open is extremely useful for library writers — especially for those who write libraries that are intended to be actually used…
Did anyone question that? (I guess the title of the thread can be a little bit irritating, but afaics, it is only the keyword that should be removed, not the feature itself).

As I told the author of this draft, I can only tell its opposers as well:
Just relax and admit that you are not fighting for the better choice, but only for the one you like better.

(btw, that is the case for a lot of decisions:
Typed throws aren't better than untyped ones, zero-based arrays aren't better than 1-based arrays, functional programming isn't better than POP or OO, composition isn't better than inheritance, structs aren't better than classes… the strongest statement you can make for some of those alternatives is that they perform better in specific situations)
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Jon Hull) #17

You could use a private abstract class and private classes instead of the protocol and structs respectively. Because they are classes, it shouldn’t even need the type erasure hack. If we end up adding submodules, then it wouldn’t need to be in the same file.

Thanks,
Jon

···

On Feb 22, 2017, at 1:41 AM, Charlie Monroe <charlie@charliemonroe.net> wrote:

On Feb 22, 2017, at 10:35 AM, Jonathan Hull <jhull@gbis.com <mailto:jhull@gbis.com>> wrote:

On Feb 21, 2017, at 11:29 PM, Charlie Monroe via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Feb 22, 2017, at 8:15 AM, Jean-Daniel via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Le 21 févr. 2017 à 17:19, Tino Heth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

I’ll concede that the proposal makes a claim that might very well be disproved. I would very much like to see an actual example of a public class that **has** to be public but **shouldn’t** be open for obvious reasons. I would happily accept being shown wrong on that point.

This is afaics one of the most active disputes on evolution — and you can save you a lot of grief by accepting that it is pointless:
The whole discussion isn't based on facts at all, despite many false claims that marking things as final is generally better.
I have asked for a single example to prove this in the past as well, so I guess no one can present such a thing to you.

To me, the largest purpose is when you have a root class ("abstract") and a few subclasses that represent various options - in Scala, this would be a case class. For various reasons, it can't be an enum - for example, you need a lot of stored data and an enum case a(Int, Int, Int, Bool, Int, Double) is not very usable.

What I have done for this case is have a protocol with several private conforming Structs, and then wrap it all in a public final class which wraps a boxed instance of one of the conformers.

It's not always possible to flatten it down to structs, sometimes you do need the class hierarchy and inheritance. ObjC support is one of the reasons, others are purely based on the need for inheritance.