[swift-evolution] Add code to super methods.

Haravikk swift-evolution at haravikk.me
Sat Nov 19 09:05:23 CST 2016


> On 16 Nov 2016, at 22:37, Sean Heber via swift-evolution <swift-evolution at swift.org> 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161119/0e48a4d4/attachment.html>


More information about the swift-evolution mailing list