<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 18, 2016, at 10:08 AM, Will Entriken &lt;<a href="mailto:fulldecent@gmail.com" class="">fulldecent@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Matthew,<div class=""><br class=""></div><div class="">This does not address the issue that a class may require all its subclasses' initializers to call one of its initializers, but does not care which one.</div></div></div></blockquote><div><br class=""></div><div>This is required by Swift’s definitive initialization rules and applies to *all* initializers. &nbsp;It isn’t really relevant to overriding in general.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><br class=""></div><div class="">Are there other languages worth investigating which have the requires super first/last semantics you note?</div></div></div></blockquote><div><br class=""></div>I don’t know of any languages that support this. &nbsp;It is not the most common semantic, but when it occurs it seems important enough that it would be better if it could be specified in the language itself and enforced rather than left to documentation.</div><div><br class=""></div><div>Here are some examples from CocoaTouch:<br class=""><div><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div><div>You can subclass&nbsp;UIPercentDrivenInteractiveTransition, but if you do so you must start each&nbsp;of your method overrides with a call to the&nbsp;super&nbsp;implementation of the method.</div></div><div><div><br class=""></div></div><div><div>// call super first and return that result if provided</div></div><div><div>UIViewController.transitionCoordinator()&nbsp;-&gt;&nbsp;UIViewControllerTransitionCoordinator?</div></div><div><div><br class=""></div></div><div><div>// call&nbsp;super&nbsp;first to retrieve the item’s existing attributes and then make your changes to the&nbsp;returned structure.</div></div><div><div>layoutAttributesForInteractivelyMovingItemAtIndexPath(_&nbsp;indexPath:&nbsp;NSIndexPath,&nbsp;withTargetPosition&nbsp;position:&nbsp;CGPoint)&nbsp;-&gt;&nbsp;UICollectionViewLayoutAttributes</div></div><div><div><br class=""></div></div><div><div>// If you override this method, you must call&nbsp;super&nbsp;first to get the invalidation context object to&nbsp;return. After getting this object, set any custom properties and return it.</div></div><div><div>func&nbsp;invalidationContextForBoundsChange(_&nbsp;newBounds:&nbsp;CGRect) -&gt;&nbsp;UICollectionViewLayoutInvalidationContext</div></div><div><div><br class=""></div></div><div><div>// call super last</div></div><div>UIView.<span class="nl" style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; font-family: Menlo, monospace;">updateConstraints</span><span style="font-family: Menlo, monospace; background-color: rgb(249, 249, 249);" class="">()</span></div></blockquote><div><div><br class=""></div><div>When I suggested having the compiler synthesize the calls in for first / last I was thinking of cases with void return. &nbsp;Several of these examples don’t have void return and the result is used in different ways. &nbsp;I no longer think the compiler should attempt to synthesize anything, but it should be able to enforce the requirement that we manually write a super call in the correct location.</div><div><br class=""></div><div>One interesting thing is that the exercise of looking for examples also turned up another semantic, <b class="">cannot</b>&nbsp;call super:</div><div><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div>UIViewController.&nbsp;loadView()</div><div>UIPresentationController.shouldPresentInFullscreen() -&gt;&nbsp;Bool</div><div>UIPresentationController.shouldRemovePresentersView() -&gt;&nbsp;Bool</div><div><br class=""></div></blockquote><div class="">That leaves us with 5 possible super semantics for overrides:</div><div class=""><br class=""></div><div class="">1) no call to super allowed</div><div class="">2) no call to super required<br class="">3) requires super (must call super *if overriden*)<br class="">4) requires super first<br class="">5) requires super last<br class=""></div><div class=""><br class=""></div><div class="">These exist in practice. &nbsp;The question is whether the language should allow them to be stated directly and enforce them or not. &nbsp;I believe it should. &nbsp;I don’t trust documentation to be complete or to be read carefully by everyone who should read it. &nbsp;Adding language support makes it clear that the proper semantics for calling super should be considered carefully and stated explicitly. &nbsp;In return the compiler ensures subclasses are well-behaved.</div><div class=""><br class=""></div>-Matthew<div class=""><br class=""></div><div class=""><br class=""><div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><br class=""></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Mon, Jan 18, 2016 at 10:19 AM, Matthew Johnson via swift-evolution <span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;</span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br class="">
&gt; On Jan 17, 2016, at 5:54 PM, Jesse Squires via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class="">
&gt;<br class="">
&gt; Hey all — this is my first reply to this list, so please forgive me if something goes wrong.<br class="">
&gt;<br class="">
&gt; I wanted to elaborate more on Nate Birkholz's earlier message about extending the 'required' keyword to class methods, other than only init.<br class="">
&gt;<br class="">
&gt; I had suggested this to Joe Groff on Twitter, and encouraged Nate to go ahead and start the thread. I’m just now finding the time to respond :) My goal here is to flesh out this idea a bit more, and hopefully get a more engaging discussion started.<br class="">
&gt;<br class="">
&gt; Subclassing in Objective-C has the following deficiencies:<br class="">
&gt;<br class="">
&gt; (1) It lacks the ability to formally declare if a method must be overridden.<br class="">
&gt;<br class="">
&gt; (2) When overriding a method, there is no mechanism to enforce a call to super. You could use NS_REQUIRES_SUPER, but not only is this barely discoverable, it isn’t part of the language. Further, it merely generates a warning when library authors most likely intend for this to be an error. (Ok, one could treat warnings as errors, etc. etc.)<br class="">
&gt;<br class="">
&gt; (3) It is easy for clients to override a superclass method without knowing it. That is, subclasses can simply implement an identical selector of the superclass without any kind of warning.<br class="">
&gt;<br class="">
&gt; Clearly this is problematic. What happens when a subclass does not call super, but should? I think the only answer is "undefined behavior". Typically, the (not so great) solution here is documentation. This is common in Cocoa and CocoaTouch, for example each time you (never) read the docs, you'll see things like "your implementation must call super at some point".<br class="">
&gt;<br class="">
&gt; Swift improves on these deficiencies in the following ways:<br class="">
&gt;<br class="">
&gt; (1) For public methods (or internal for classes in the same module), Swift requires the 'override' keyword. This is great. Clients are now aware that they are overriding a superclass method. Though this *should* be an indication to the client that super might need to be called and the docs should be read (lol), clients are not required to do either.<br class="">
&gt;<br class="">
&gt; (2) Superclasses can prevent overriding using the 'final' keyword. This provides a lot of safety but results in an "all or nothing" decision for library authors.<br class="">
&gt;<br class="">
&gt; (3) For initializers only, Swift enforces the 'override' keyword *and* a call to super due to Swift’s strict initialization rules. Thus, client subclasses can safely override initializers. Woo!<br class="">
&gt;<br class="">
&gt; (4) Additionally, for initializers only, Swift superclasses can require that subclasses implement a specific initializer using the 'required' keyword (given that a subclass provides a custom init). Again, augmenting the subclass initialization flow can be done safely. ::applause::<br class="">
&gt;<br class="">
&gt; OK. Hopefully I didn’t miss anything there. As you can see, there’s one major deficiency remaining in Swift:<br class="">
&gt;<br class="">
&gt; - If a subclass chooses to override a non-final method of its superclass, there is no mechanism to require a call to super.<br class="">
&gt;<br class="">
&gt; My proposed solution is straight-forward: extend the use of 'required' to methods, rather than only allow this for init.<br class="">
&gt;<br class="">
&gt; Behavior would be the following:<br class="">
&gt;<br class="">
&gt; - A superclass can specify a method as 'required'.<br class="">
&gt; - *If* a client’s subclass chooses to override a 'required' method, it must call super.<br class="">
&gt; - Without the 'required' keyword, current behavior would remain the same.<br class="">
<br class="">
</span>Thanks for bringing up this topic.&nbsp; I agree that we need to support more expressive semantics for overrides.&nbsp; I would take a slightly different approach though.<br class="">
<br class="">
Your use of `required` has a different semantic than its use for initializers.&nbsp; The change is arguably subtly, but it is meaningful.&nbsp; I don’t think it is a good idea for it to have different semantics in different contexts.<br class="">
<br class="">
For initializers `required` means “subclasses must provide an initializer with this signature.&nbsp; The fact that you have to call super just falls out of that because it is an initializer.&nbsp; You don’t actually have to call designated initializer that has the matching signature.<br class="">
<br class="">
You are suggesting making `required` mean “you must call the exact same method on super”.&nbsp; This would be unnecessarily limiting.<br class="">
<br class="">
There are 3 possible semantics for overridability:<br class="">
<br class="">
1) final / not overridable<br class="">
2) overridable<br class="">
3) required<br class="">
<br class="">
I suggest expanding the use of `required` to mean #3 in general.&nbsp; I would also suggest changing the default to #1.&nbsp; That would require developers to think about subclasses before allowing overrides and also decide whether #2 or #3 is the correct semantics when overriding is allowed (I know this is controversial and somewhat orthogonal to your idea).&nbsp; This would prompt the developer to think about the requirements to call super, which I discuss next.<br class="">
<br class="">
There are also 4 possible semantics for "super requirements” when you do override:<br class="">
<br class="">
1) no call to super required<br class="">
2) requires super (must call super *if overriden*)<br class="">
3) requires super first<br class="">
4) requires super last<br class="">
<br class="">
NS_REQUIRES_SUPER is equivalent to #2.<br class="">
<br class="">
The last two are somewhat subtle, but it is occasionally reasonable for a superclass to want its implementation to run before or after a subclass implementation.&nbsp; In both of these cases I would advocate for the compiler to automatically synthesize the call to super (if Swift supports these semantics) rather than requiring the developer to write the call.&nbsp; The annotation specifies the behavior and the manual call would be redundant.<br class="">
<br class="">
Swift doesn’t currently have any rules around calling super so we have #1 as a de-facto default with no way to change that.&nbsp; That is probably ok as a default, especially if we require developers to think about subclasses when writing an overridable method (by making final the default).&nbsp; If we introduce syntax to specify 2-4 we would have all cases covered.<br class="">
<br class="">
Any of the “super requirements” could be specified in conjunction with either `overridable` or `required`.&nbsp; This allows more expressiveness than mixing the two concepts together would support.<br class="">
<br class="">
At minimum, I suggest that you use `required` as mentioned above and introduce new syntax to mean “must call the super implementation of the same method”.&nbsp; Adding “super first” and “super last” would be nice as well, but can also be added later if you’re not interested in those semantics.<br class="">
<br class="">
Matthew<br class="">
<div class="HOEnZb"><div class="h5"><br class="">
&gt;<br class="">
&gt; Comments from Joe via twitter:<br class="">
&gt; - "Should be straight forward to implement."<br class="">
&gt; - "One interesting thing it would enable is invariant implementations of covariant protocol requirements." &lt;dogScience.png&gt;<br class="">
&gt;<br class="">
&gt; Thanks for reading!<br class="">
&gt; Jesse<br class="">
&gt;<br class="">
&gt; _______________________________________________<br class="">
&gt; swift-evolution mailing list<br class="">
&gt; <a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
<br class="">
_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</div></div></blockquote></div><br class=""></div>
</div></blockquote></div><br class=""></div></body></html>