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

Scott James Remnant scott at netsplit.com
Mon Jul 18 12:59:16 CDT 2016


> On Jul 18, 2016, at 10:12 AM, John McCall <rjmccall at apple.com> wrote:
> 
>> On Jul 17, 2016, at 3:12 PM, Scott James Remnant via swift-evolution <swift-evolution at swift.org> wrote:
>> I disagree that an `open` method overridden from a superclass is implicitly `open`.
>> 
>> As the rationale for the proposal states, overridability is hard to get right, and there is no guarantee that the consumer of an API is going to think about it. The default for override methods should not be `open` or `final`, it should be the internal equivalent.
>> 
>> A coder subclassing a public API, who themselves wants their subclass to be subclassable, should need to restate `open` where appropriate.
> 
> I don't think that defaulting to non-open would be a good idea.  Like I covered in the proposal, inherited open methods remain open; letting an override implicitly close off an open method would create a pretty unfortunate error-of-omission situation.
> 
> We could remove the default here and require the method to be explicitly open/nonopen/final, but then we really do pile up the modifiers:
> 
>  public open override func foo()
> 
> To me, the fact that it's already marked with "override" suggests the possibility of open-ness enough to remove the need to re-state it.  I can see why you might disagree, though.
> 

I think that this explicitness is more Swifty.

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

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

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

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

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


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

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

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

But the function level too:

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

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


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

Scott


More information about the swift-evolution mailing list