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


> On Jun 27, 2016, at 5:08 PM, Javier Soto <[email protected]> wrote:
> 
> That is a very good point, it should be explicitly mentioned in the proposal. 
> My thought would be that since in the Obj-C runtime it's not possible to 
> guarantee a class won't have subclasses, or that a method is not overriden, 
> Obj-C classes would be imported as open. 
> 
> On the Swift side, I think today it's possible to declare a "public final 
> @objc class", but you can still inherit from it from Obj-C, right? My hunch 
> would be that that should be disallowed, but perhaps there's a reason why 
> it's allowed today. 
> On Mon, Jun 27, 2016 at 4:25 PM Michael Ilseman <[email protected] 
> <mailto:[email protected]>> wrote:
> Could you elaborate on how we should treat classes imported from Objective-C 
> or CF-style C? That is, do we always annotate them as being “open” because 
> those paradigms permit subclassing anywhere, or do you propose some kind of 
> recommended “sealed” audit, or what?
> 
> 
>> On Jun 27, 2016, at 3:40 PM, Javier Soto via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
> 
>> Hello!
>> 
>> I sent this as a PR <https://github.com/apple/swift-evolution/pull/376> on 
>> the swift-evolution repo, but we never had any discussion about it on-list, 
>> besides a long time ago 
>> <http://thread.gmane.org/gmane.comp.lang.swift.evolution/9702/focus=9708>. 
>> Here's the first draft of the proposal:
>> 
>> 
>> Sealed classes by default
>> 
>>  
>> <https://github.com/JaviSoto/swift-evolution/blob/a46877afb0302d2b03fa493255f5ced04ccb7f34/proposals/0000-sealed-by-default.md#introduction>Introduction
>> 
>> Introduce a new sealed class modifier that makes classes and methods final 
>> outside of the module they're declared in, but non-final within the module.
>> 
>>  
>> <https://github.com/JaviSoto/swift-evolution/blob/a46877afb0302d2b03fa493255f5ced04ccb7f34/proposals/0000-sealed-by-default.md#motivation>Motivation
>> 
>> It is not uncommon to have a need for a reference type without needing 
>> inheritance. Classes must be intentionally designed to be subclassable, 
>> carefully deciding which methods are the override entry-points such that the 
>> the behavior remains correct and subclasses respect the Liskov substitution 
>> principle <https://en.wikipedia.org/wiki/Liskov_substitution_principle>.
>> Defaulting to non-final allows the author of a class to accidentally leave 
>> the visible methods open for overrides, even if they didn't carefully 
>> consider this possibility.
>> Requiring that the author of a class mark a class as open is akin to 
>> requiring symbols to be explicitly public: it ensures that a conscious 
>> decision is made regarding whether the ability to subclass a class is part 
>> of the API.
>>  
>> <https://github.com/JaviSoto/swift-evolution/blob/a46877afb0302d2b03fa493255f5ced04ccb7f34/proposals/0000-sealed-by-default.md#proposed-solution>Proposed
>>  solution
>> 
>> New sealed (actual name pending bike-shedding) class modifier for classes 
>> and methods which marks them as only overridable within the module they're 
>> declared in.
>> sealed becomes the default for classes and methods.
>> New open (actual name pending bike-shedding) class modifier to explicitly 
>> mark a class or a method as overridable.
>>  
>> <https://github.com/JaviSoto/swift-evolution/blob/a46877afb0302d2b03fa493255f5ced04ccb7f34/proposals/0000-sealed-by-default.md#detailed-design>Detailed
>>  design
>> 
>> Code Examples:
>> 
>> /// ModuleA:
>> 
>> /// This class is `sealed` by default.
>> /// This is equivalent to `sealed class SealedParentClass`
>> class SealedParentClass {
>>     /// This method is `sealed` by default`.
>>     func foo()
>> 
>>     /// This raises a compilation error: a method can't have a 
>> "subclassability"
>>     /// level higher than that of its class.
>>     open func bar()
>> 
>>     /// The behavior of `final` methods remains unchanged.
>>     final func baz()
>> }
>> 
>> open class OpenParentClass {
>>     /// This method is `sealed` by default`.
>>     func foo()
>> 
>>     /// Overridable methods in an `open` class must be explicitly marked as 
>> `open`.
>>     open func bar()
>> 
>>     /// The behavior of a `final` method remains unchanged.
>>     final func baz()
>> }
>> 
>> /// The behavior of `final` classes remains unchanged.
>> final class FinalClass { }
>> /// ModuleB:
>> 
>> import ModuleA
>> 
>> /// This raises a compilation error: ParentClass is effectively `final` from
>> /// this module's point of view.
>> class SubclassA : SealedParentClass { }
>> 
>> /// This is allowed since `OpenParentClass` has been marked explicitly `open`
>> class SubclassB : OpenParentClass {
>>     /// This raises a compilation error: `OpenParentClass.foo` is
>>     /// effectively `final` outside of `ModuleA`.
>>     override func foo() { }
>> 
>>     /// This is allowed since `OpenParentClass.bar` is explicitly `open`.
>>     override func bar() { }
>> }
>>  
>> <https://github.com/JaviSoto/swift-evolution/blob/a46877afb0302d2b03fa493255f5ced04ccb7f34/proposals/0000-sealed-by-default.md#impact-on-existing-code>Impact
>>  on existing code
>> 
>> This would be a backwards-breaking change for all classes and methods that 
>> are public and non-final, which code outside of their module has overriden. 
>> Those classes/methods would fail to compile. Their superclass would need to 
>> be changed to open.
>>  
>> <https://github.com/JaviSoto/swift-evolution/blob/a46877afb0302d2b03fa493255f5ced04ccb7f34/proposals/0000-sealed-by-default.md#alternatives-considered>Alternatives
>>  considered
>> 
>> Defaulting to final instead: This would be comparable to Swift defaulting to 
>> private, as opposed to internal. Just like internal is a better trade-off, 
>> sealed by default also makes sure that getting started with Swift, writing 
>> code within a module, doesn't require a lot of boilerplate, and fighting 
>> against the compiler.
>> -- 
>> Javier Soto
> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> -- 
> Javier Soto

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to