> On 16 Nov 2016, at 22:37, Sean Heber via swift-evolution 
> <[email protected]> wrote:
> 
> That could be kind of neat - perhaps a syntax more like this so that there 
> isn’t another bare keyword:
> 
> override(after) func viewDidLoad() {
> }
> 
> and:
> 
> override(before) func viewDidLoad() {
> }
> 
> Which would allow you to specify where your code happens - either before or 
> after the superclass method, essentially. Leaving out before/after would 
> still behave as expected and you’d have to call super yourself (or not):
> 
> override func viewDidLoad() {
>  // stuff
>  super.viewDidLoad()
>  // more stuff
> }
> 
> 
> A potentially neat thing about this is that you could possibly then impose 
> restrictions on subclasses like so:
> 
> final(before) func viewDidLoad() {}
> 
> Which could mean that the “before” slot is “final” - therefore you cannot do 
> either of these:
> 
> override func viewDidLoad() {}
> override(before) func viewDidLoad() {}

I like the basic idea, and I especially like the clarification via override at 
the call site, but I wanted to add the design that I preferred from the last 
discussion.

Basically the idea was that the parent method would have a @super() attribute 
with of the following attributes available to use within it:

before: super must be called before all other statements in an overriding 
method's body.
required: the super call is required. If neither before or after is specified 
it may be placed anywhere in the method's body, but must occur in all paths. 
This is the default if a method has a @super attribute.
optional: the super call is not required.
after: super must be called after all other statements in an overriding 
method's body.
error: failing to call the super method either at all or in the correct 
location is an error. This is the default.
warning: failing to call the super method either at all or in the correct 
location is a warning that a developer may choose to ignore.

So a method with @super is equivalent to @super(optional), while a method with 
a plain @super attribute is equivalent to @super(required, error)

I really like the idea of using override(before) at the call-site as a 
shorthand for having the super call as the first statement behind the scenes, 
and likewise for final(after).

However, with regards to a plain override, I think it should still be 
permitted, but the compiler will check for the presence of the super call, and 
that it meets the criteria specified (if any). One further caveat is that 
non-mutating statements (or pure functions?) should be permitted somehow, alone 
with simple statements, as this allows variables to be prepared, log-entries 
created etc. without breaking the super requirement. So for example you could 
do:

        class Foo { @super(before) func someMethod(foo:T) {} }
        class Bar extends Foo {
                override func someMethod(foo:T) {
                        var foo = foo
                        print(foo)
                        mutateFooViaInout(foo) // This is a non-mutating or 
pure function that changes its input via inout
                        super.someMethod(foo) // This is still the start as far 
as @super(before) is concerned
                }
        }

Part of the problem with this is that it's difficult to add the flexibility 
required for classes, since they don't have the concept of 
mutating/non-mutating; so this means we'd have to wait for that to be added 
and/or detection of pure functions (unless it's easy to detect already, I don't 
know), otherwise the @super(before) and @super(after) conditions may be too 
restrictive, and have to be delayed till later.

The main remaining argument was whether it is possible for the API designer to 
get the before/after requirement right, but then this is why I suggest the 
ability to make it a warning rather than an error (it could even be the default 
if people prefer). But I think in general API designers shouldn't add a @super 
attribute unless they know with certainty what they need from their design; for 
example if properties aren't properly instantiated/loaded unless the super 
method is called first, then that's a good reason to user @super(before), if 
there are a bunch of private properties that must be kept up-to-date then 
@super(required) and so-on.

Otherwise if the API designer specifies nothing, we still get a nice addition 
to override at the call-site to remove a little boiler-plate and keep our 
sub-class methods clean.
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to