[swift-evolution] Replace the override keyword by 'extend' and 'replace' or add an annotation like @SuppressSuperCall

Howard Lovatt howard.lovatt at gmail.com
Tue Feb 16 16:55:04 CST 2016


@Haravikk,

I am not perticularly fussed about the exact syntax so long as it is clear
and consistent, it is the semantics I am most interested in. I would say
just go with what is the most popular syntax. The syntax I suggested is
clear, consistent, and concise, that is why I suggested it, EG instead of:

    @super(option) override func name() { ... }

I am suggesting

    override(option) name() { ... }

Its only syntax :). Either is fine because they are both clear and
consistent.

Changing tack to abstract methods and classes. Maybe it is necessary to
propose abstract methods and classes for Swift with a future expansion
section noting that it is the intention to add control over when super is
called at a later date and giving some examples. That way abstract classes
can be added with systax that can be extended to accommodate more control
at a later date. The problem with doing two seperate proposals is that the
syntax could become inconsistent.

Thanks for starting this thread, I think it would be a valuable addition to
Swift.

 -- Howard.

On Wednesday, 17 February 2016, Haravikk <swift-evolution at haravikk.me>
wrote:

> Woah, pretty expansive and well thought out set of rules here!
>
> On 16 Feb 2016, at 03:36, Howard Lovatt <howard.lovatt at gmail.com
> <javascript:_e(%7B%7D,'cvml','howard.lovatt at gmail.com');>> wrote:
>
>     1. Make methods and classes final by default and mark an overridable
> class with `class(option)` or `class(replace)` (see below for
> `class(replace)`).
>
>
> This is a great idea, it’s definitely better to force the developer to
> think about extension and explicitly declare it, and having the whole thing
> self-documenting will make it so much easier.
>
>     2. A function declaration requires one of `func`, `func(final)`,
> `func(replace)`, `func(option)`, `func(before)`, `func(after)`, or
> `func(instead)` keywords and a function override requires one of
> `override`, `override(final)`, `override(replace)`,
> `override(option)`, `override(before)`, `override(after)`, or
> `override(instead) - note no func keyword.
>
>
> I’m not so sure about putting this into the keywords. Personally I think
> an attribute is a bit neater (it can go nicely above the function
> declaration). Meanwhile with override I think it’s probably enough to just
> override a method, as this implicitly agrees to whatever rules were set out
> by the super-method. If want to put your own requirements on sub-classes
> even further down the chain then you just add the attribute to your own
> method.
>
>     6. A class with a method without a body, which must be marked
> `func/override` or `func/override(replace)`, has to be marked
> `class(replace)`; it is abstract. (Note the notation `class(option)` and
> `class(replace)` is consistent, a `class(option)` has at least one
> optionally overridable method and no `func/override(replace)` methods,
> whereas a class with at least one `func/override(replace)` method is marked
> `class(replace)`.)
>
>
> I like this, but would an abstract keyword not be simpler and clearer to
> most? Setting it on a class would allow that class to contain abstract
> methods (and properties?) also declared with the abstract keyword. An
> abstract method could contain no body (child class must give full
> implementation) or could include a body in which case it must be extended
> and called.
>
>    7. Any of the annotations can be extended with final, e.g.
> `func(optional, final)` means it is overriding a `func(optional)` but from
> this point down it is final. Final methods must have a body.
>
>    8. In a class/protocol `func` is shorthand for `func(final)` unless the
> method has no body in which case it is shorthand for `func(replace)`.
>    9. `override` is a shorthand for `override(A, final)` where A is the
> annotation specified in the matching `func` declaration.
>    10. Overriding methods in a final class do not require the extra final
> annotation, e.g. in a final class `func(option)` and `func(option, final)`
> are equivalent.
>
>
> I think my preference is still towards an attribute to specify the
> requirements for sub-classes overriding a method, with the override keyword
> implicitly agreeing to those conditions rather than having to repeat them.
> If you want to change those requirements for further levels of sub-class
> then you can just add the same attribute your own methods, like so:
>
> class MyClass {
> @super(required)
> func mustCallMe() { … } // Immediate sub-classes must call this method
>
> @super(optional)
> func someOtherMethod() { … } // Call super, or not, this method doesn’t
> care
> }
>
> class MySubClass : MyClass {
> @super(before)
> override func mustCallMe() { … } // Further sub-classes must now call this
> first
>
> override func someOtherMethod() { … } // This implicitly agrees to
> optionally include the parent call and
> // is final due to the lack of a @super attribute of its own (or one on
> its class).
> }
>
> If an overriding method has no @super attribute of its own then it is
> implicitly final, unless the attribute is instead placed on the class
> (allowing us to make a class’ methods all overridable if we like).
>
> I dunno, it may just be personal preference; I can completely get wanting
> to clarify what rules are being followed at each step, but I’m just unsure
> whether the extra complexity is worth it? I can definitely see the need to
> introduce more options over the three I gave though, giving us:
>
>
>    - *required*: parent method must be called somewhere in all code paths
>    of overriding method.
>    - *optional*: parent method may or may not be called anywhere in the
>    overriding method.
>    - *replace*: parent method may not be called at all by overriding
>    method (sub-class must provide total replacement).
>    - *before* and *after*: these imply required but can also be set as
>    optional (to be read as “if included, parent call must come first/last”).
>    Not sure if after should require the parent method’s return value to be
>    used in methods with a return type?
>
>
> I think that abstract methods and classes should probably be a separate
> proposal building upon these extension requirements. In essence though an
> abstract method with no body would imply @super(replace). An abstract
> method with a body implies @super(required), but could anything other than
> @super(replace) would be valid, allowing an abstract class to provide a
> sample implementation that need not be used in sub-classes, optionally
> setting a before/after requirement in the event that it is used.
>
> Thoughts? I’m not too fussy about the exact syntax, but I think that while
> repeating the requirements in the override is explicit (which is usually a
> good thing) I personally think that the override keyword alone should
> suffice, as anyone creating a sub-class should know what the requirements
> of the parent are and agreed to them. What’s important is really whether
> the overriding method itself has any requirements for classes further down
> the hierarchy I think.
>
> I also think it could be interesting to allow @super on the class itself,
> allowing the developer to decide if they want to keep the implicitly final
> default, or make their methods implicitly overridable, in which case they
> can then use the final keyword to put it back again.
>
> Lastly, I’m not sure about the use of an attribute actually as I’m not
> clear on what the rules for them really are (if there are any?). I quite
> like how they look and they’re already setup to support multiple options
> etc., but adding options to a keyword may make sense. If we do that though
> then personally I think we could just re-use super, e.g-:
>
> class MyClass {
> super(required) func mustCallMe() { … }
> }
>
> I suppose there’s no reason this couldn’t go on func() like you suggest,
> but I like the consistency with the fact that it’s the super keyword in the
> method body that this feature is controlling.
>


-- 
-- Howard.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160217/8c6d095e/attachment.html>


More information about the swift-evolution mailing list