<div dir="ltr">On Mon, Jul 18, 2016 at 7:07 AM, Károly Lőrentey <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 2016-07-18 09:17:43 +0000, David Hart via swift-evolution said:<br>
<br>
</span><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
On 18 Jul 2016, at 11:11, Xiaodi Wu via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br>
<br>
On Mon, Jul 18, 2016 at 3:27 AM, Brent Royal-Gordon via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br>
> On Jul 17, 2016, at 8:57 PM, L. Mihalkovic via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br>
><br>
>> On Jul 17, 2016, at 9:14 PM, Garth Snyder via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br>
>><br>
>> Is there a summary somewhere of the motivation for allowing methods to be declared non-overridable within open classes?<br></span>
[...]<span class=""><br>
Garth: I think it's implicit in the reasons to prevent subclassing. The mere fact that a class allows subclassing doesn't necessarily mean that every member in it is designed to be subclassed. Consider `UIViewController`: It's obviously designed to be subclassed, and some methods in it (such as `loadView`) are intended to be overridden, but others (such as `loadViewIfNeeded`) are *not* intended to be overridden.<br>
<br>
And [if UIViewController were to be written in Swift] there'd be a good reason why `loadViewIfNeeded` and others of its ilk couldn't be final? <br>
<br>
I don't know UIKit internals, but I could imagine loadViewIfNeeded be overridden internally, if one knows the precise internal workings of UIViewController. That would require open, to allow overriding internally but not externally.<br>
</span></blockquote>
<br>
<br>
I thought about this aspect a little more. I think it's fair to say that we're breaking new ground for language design here. Classes limiting inheritance to a certain set of subclasses are nothing new (I've written & used classes doing this in C++, Java and C#), but no language that I know of allows limiting overrides of a specific public member in such a way. I think we need a convincing rationale for making this esoteric middle ground between final and open members the new default.<br>
<br>
The UIKit example above isn't convincing at all. It is already quite easy to allow package-internal subclasses to configure the behavior of loadViewIfNeeded without such a novel language feature. E.g., the UIKit team can simply make loadViewIfNeeded call into a non-final but internal method:<br>
<br>
public open class UIViewController {<br>
private var _view: UIView? = nil<br>
<br>
public final func loadViewIfNeeded() {<br>
internalLoadViewIfNeeded()<br>
}<br>
<br>
internal func internalLoadViewIfNeeded() { // overridable internally<br>
if let view = _view { return }<br>
loadView()<br>
}<br>
<br>
public open func loadView() {<br>
// Load it from a nib or whatevs<br>
}<br>
}<br>
<br>
I see no drawback to this pattern; it is quite clear and simple. Therefore, in the interest of keeping the language free of needless complexity, I suggest we change the proposal to remove the implicit "sealed" level of public member overridability, and support only "open" or "final" class members.<br></blockquote><div><br></div><div>I'm impressed by this analysis. You've convinced me that the proposed default for public members is rather esoteric; given this very clean alternative way of achieving the same result, an esoteric default (though formally consistent with Swift conventions) seems unduly burdensome.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
For members, "open" should mean the opposite of "final", with no levels in between. Member-level openness should be entirely independent of visibility; so it should be possible to say "internal open" to mean an internally overridable member that's not at all visible outside the module -- the same as today's default.<br>
<br>
(Note that (on platforms with an Objective-C runtime) "dynamic" provides a third level of flexibility for class members; I argue that it should imply "open". So in order of increasing flexibility, we'd have "final", "open" and "dynamic" members. This seems easy enough to describe and understand.)<br>
<br>
I also suggest that for now, we should make neither "final" nor "open" nor "dynamic" the default for public members of open classes: we should rather require class authors to explicity add one of these qualifiers to all public member declarations. This way, we can defer the argument for choosing a default to a later (additive) proposal, once we have some experience with this setup. Non-public members can safely keep defaulting to "internal open", like they do today.<span class="HOEnZb"><font color="#888888"><br>
<br>
-- <br>
Károly<br>
@lorentey</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
<br>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</div></div></blockquote></div><br></div></div>