[swift-evolution] Proposal: Add @requires_super attribute

Marc Knaup marc at knaup.koeln
Wed Dec 16 13:22:19 CST 2015


When requiring super's implementation to always be called Swift should not
make the assumption that two methods with the same name but different
signatures are interchangeable.
Only the super method with exactly the same signature - i.e. the overridden
one - should be allowed to called. Anything else will likely be complex and
confusing.

@Ian "override" keyword is neither necessary nor allowed when "required" is
used since it implies exactly that already.

On Wed, Dec 16, 2015 at 8:17 PM, Ian Ynda-Hummel via swift-evolution <
swift-evolution at swift.org> wrote:

> @Jordan I might slowly be convincing myself that initialization behavior
> is correct, though. For example, this feels right:
>
>     class Foo {
>         required func foo() {
>
>         }
>     }
>
>     class Bar: Foo {
>         required func foo(bar: Bar) {
>             super.foo()
>         }
>     }
>
> This, however, feels less right:
>
>     class Foo {
>         required func foo(string: String) {
>
>         }
>
>         required func foo(url: NSURL) {
>
>         }
>     }
>
>     class Bar: Foo {
>         override required func foo(string: String) {
>             super.foo(url: NSURL(string: string)!)
>         }
>     }
>
> But regardless, I'm having trouble coming up with a better keyword.
>
> fo
> On Wed, Dec 16, 2015 at 2:03 PM T.J. Usiyan <griotspeak at gmail.com> wrote:
>
>> +1
>>
>> I thought that there must have been some reason not to include it that I
>> hadn't considered when it wasn't in Swift 1.0.
>>
>> On Wed, Dec 16, 2015 at 1:59 PM, Jordan Rose via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>>> My hesitation about "required" is that required initializers don't have
>>> to call the *same* initializer, which is something that
>>> NS_REQUIRES_SUPER *does* enforce. (In fact, this new attribute could
>>> very well apply to required initializers as well: if you implement this
>>> initializer, you must chain to the same initializer. I'm not quite sure
>>> when that would come up, but it's potentially useful.)
>>>
>>> Jordan
>>>
>>> On Dec 16, 2015, at 10:56 , Ian Ynda-Hummel via swift-evolution <
>>> swift-evolution at swift.org> wrote:
>>>
>>> +1 for this if for nothing else but UIKit classes yelling at me to call
>>> super.viewDidLoad().
>>>
>>> I think using the required keyword makes sense. The one possible caveat
>>> is overloading, as my knee jerk reaction is that methods of the same name
>>> would behave like initializers. So a method overriding a required method
>>> would have to call a required method of the same name on the superclass if
>>> one exists. I'm not convinced that's correct, though.
>>>
>>> On Wed, Dec 16, 2015 at 1:40 PM Marc Knaup via swift-evolution <
>>> swift-evolution at swift.org> wrote:
>>>
>>>> "required" also doesn't mean that a subclass has to implement the
>>>> required initializer since it can be inherited.
>>>> Your example is an abstract function which should have it's own keyword
>>>> (if we ever get abstract functions).
>>>>
>>>> On Wed, Dec 16, 2015 at 7:37 PM, Vester Gottfried <
>>>> vester.gottfried at gmail.com> wrote:
>>>>
>>>>> I think reusing required would send the wrong message. Required would
>>>>> mean for me something like NSOperation subclasses maybe require to have a
>>>>> main() function, but that doesn't mean you have to call super. On the
>>>>> contrary, the documentation of NSOperation main() explicitly states not to
>>>>> call super.
>>>>>
>>>>> On Wed, Dec 16, 2015 at 7:08 PM, Marc Knaup <marc at knaup.koeln> wrote:
>>>>>
>>>>>> What about re-using the "required" keyword in the superclass which
>>>>>> already means something similar for initializers?
>>>>>> Subclass implementations are required to call super's implementation.
>>>>>> If a subclass doesn't implemented the required method it could mean
>>>>>> that it inherits the behavior from the superclass - just like initializers
>>>>>> can be inherited too.
>>>>>>
>>>>>> On Wed, Dec 16, 2015 at 7:02 PM, Jordan Rose <jordan_rose at apple.com>
>>>>>> wrote:
>>>>>>
>>>>>>> +1 from me. FWIW, the Objective-C one is syntactic.
>>>>>>>
>>>>>>> Information from Radar: the request for this is
>>>>>>> rdar://problem/17408107 (plus a few duplicates). One of the dups
>>>>>>> suggests a variation where a subclass method can be declared as "refine"
>>>>>>> instead of "override" so that you can document that your *own* method
>>>>>>> is expected to call super. In this model, "@requires_super" could become
>>>>>>> something like "imposed". I personally think this doesn't add enough,
>>>>>>> especially since we wouldn't be publishing refine-vs-override in a
>>>>>>> library's public interface.
>>>>>>>
>>>>>>> Jordan
>>>>>>>
>>>>>>> On Dec 16, 2015, at 9:49 , Marc Knaup via swift-evolution <
>>>>>>> swift-evolution at swift.org> wrote:
>>>>>>>
>>>>>>> Sounds reasonable since even the best flow analysis cannot ensure
>>>>>>> that all codepaths call the super implementation.
>>>>>>>
>>>>>>> Some more edge cases:
>>>>>>>
>>>>>>>    - Calling super asynchronously by using it in a closure
>>>>>>>    - Referring to the super implementation by assign it to a
>>>>>>>    variable and call it later (is that really possible? never did that)
>>>>>>>
>>>>>>>
>>>>>>> On Wed, Dec 16, 2015 at 6:25 PM, Vester Gottfried <
>>>>>>> vester.gottfried at gmail.com> wrote:
>>>>>>>
>>>>>>>> I would suggest that @requires_super only checks if a call to super
>>>>>>>> is present at all. More detailed behaviour should be part of the functions
>>>>>>>> documentation, because I think all possibilities cannot be checked easily
>>>>>>>> by the compiler. For example a call to super my be required to happen early
>>>>>>>> or late inside the function. But when too early or too late is can probably
>>>>>>>> not been forseen by the compiler.
>>>>>>>>
>>>>>>>> On Wed, Dec 16, 2015 at 5:46 PM, Marc Knaup <marc at knaup.koeln>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> +1 always had such issues with UIViewController's lifecycle
>>>>>>>>> methods.
>>>>>>>>>
>>>>>>>>> But edge cases need to be considered like "throws" for example.
>>>>>>>>> Do I need to call super before I throw something?
>>>>>>>>>
>>>>>>>>> On Wed, Dec 16, 2015 at 5:41 PM, Matthew Johnson via
>>>>>>>>> swift-evolution <swift-evolution at swift.org> wrote:
>>>>>>>>>
>>>>>>>>>> +1 to this.  Anything that helps ensure inheritance is thought
>>>>>>>>>> through carefully and used correctly is a win.
>>>>>>>>>>
>>>>>>>>>> On Dec 16, 2015, at 10:32 AM, Vester Gottfried via
>>>>>>>>>> swift-evolution <swift-evolution at swift.org> wrote:
>>>>>>>>>>
>>>>>>>>>> Some class based libraries/frameworks expect the consumer to
>>>>>>>>>> subclass certain classes and override specific method and require that the
>>>>>>>>>> super implementation of an overridden method is being called.
>>>>>>>>>>
>>>>>>>>>> Not calling the super implementation is a common source of bugs
>>>>>>>>>> that may be prevented if the compiler checks if super is called, like it
>>>>>>>>>> does in some cases of init().
>>>>>>>>>>
>>>>>>>>>> Example:
>>>>>>>>>>
>>>>>>>>>> class Box {
>>>>>>>>>>    @requires_super
>>>>>>>>>>     func addStuff() { ... }
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> Overriding class Box's addStuff without calling super.addStuff()
>>>>>>>>>> should result in an error
>>>>>>>>>>
>>>>>>>>>> class Chest : Box {
>>>>>>>>>>     override addStuff() {
>>>>>>>>>>          // ERROR: addStuff() requires call to super.addStuff()
>>>>>>>>>>         ...
>>>>>>>>>>     }
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> Objective-C developers know this as NS_REQUIRES_SUPER and I think
>>>>>>>>>> its worth thinking about adapting it.
>>>>>>>>>>
>>>>>>>>>> I hope my proposal was clear and thanks for reading,
>>>>>>>>>>
>>>>>>>>>> Gottfried
>>>>>>>>>>  _______________________________________________
>>>>>>>>>> swift-evolution mailing list
>>>>>>>>>> swift-evolution at swift.org
>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> swift-evolution mailing list
>>>>>>>>>> swift-evolution at swift.org
>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>  _______________________________________________
>>>>>>> swift-evolution mailing list
>>>>>>> swift-evolution at swift.org
>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>>
>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>>
>>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151216/d5d8d06f/attachment.html>


More information about the swift-evolution mailing list