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
