On 16 February 2016 at 09:56, Haravikk via swift-evolution < swift-evolution@swift.org> wrote:
Oh, it looks like Alexey beat me to a similar solution, but split the
thread (at least in Mail.app):
On Mon, Feb 15, 2016 at 2:07 PM Alexey Demedetskiy via swift-evolution < > swift-evolution@swift.org> wrote:
Hi
I would like to suggest you to extend your proposal.
In my practice, overriding super functions can have several semantics.
1) Replace - simple case for abstract classes which implementation do
nothing, or throw an exceptions.
2) After super - things like viewDidLoad and viewWillAppear, setUp etc.
All cases where super expect to be called before child code.
3) Before super - opposite to 2.
4) Override - no rules about order, but super call must be done.
So code can look like:
override(after) func viewDidLoad() {
// super.viewDidLoad() <— no need to call super at first line.
// child code
}
override(before) func tearDown() {
// clean code
// super… inserted by compiler
}
override(instead) func loadView() {
// super.loadView() <— marked as an error with appropriate fix-up to
remove instead modifier
}
override func refillHealthBar() {
// absent call to super will cause an error with fix-up to add (instead)
modifier
}
I am not sure about exposing this in a public interface and limit child
override options.
But in general - what is your thoughts about this approach to problem that
you mention?
On 15 Feb 2016, at 22:52, Haravikk via swift-evolution < > swift-evolution@swift.org> wrote:
This is an interesting idea, and fits well with the theme of preventing
mistakes in Swift, but I think that the proposed solution isn’t flexible
enough, as there are cases for inheritance patterns where extending doesn’t
actually make sense, so having to specify an exception every time could
quickly become annoying.
I think the better solution is to instead allow super-classes to specify
whether or not their method must be called when overridden/extended. For
example:
class View {
@super(required) func viewDidLoad() { … }
}
class Button : View {
override func viewDidLoad() { … }
}
class Widget : View {
override func viewDidLoad() {
super.viewDidLoad()
…
}
}
In this extension of your example Button will cause an error because it
overrides viewDidLoad() but fails to call the parent’s method as required
by the @super attribute. However, Widget compiles successfully because it
follows the requirement.
So the options for @super would be:
- *required: *child-class must call parent implementation of this
method.
- *optional:* default behaviour, child can choose whether to call the
parent’s method.
- *denied:* child may not call parent’s method (useful if it makes
assumptions that a child-class may not follow), but can still
extend/override.
I think this would be a more flexible solution to the problem, and put the
decision in the hands of those writing classes designed for inheritance.
I’m not 100% sure of whether to rename override to extend, I like extend
better personally, but it probably doesn’t matter overall.
On 15 Feb 2016, at 20:57, Florian Liefers via swift-evolution < > swift-evolution@swift.org> wrote:
Hi!
I would like to suggest to replace the override keyword for functions by
something like extend and replace or to add an annotation like
@SuppressSuperCall (don’t know a good name for it).
The reason for this is, that it might happen, that one forgets to call the
super’s implementation in an overridden function or if one reads the code
it might not be obvious why the super’s implementation is not called:
class View {
func viewDidLoad() {
// does something
}
}
class Button: View {
override func viewDidLoad() {
super.viewDidLoad() // <— this might be forgotten
// do something other
}
}
The compiler will accept if one overrides a superclass’s function but does
not call the superclass’s implementation which is often ok. The developer
should clearly state that he doesn’t want to call the superclass’s
implementation, otherwise the compiler should throw an error.
// Example for extending a function
class Button: View {
extend func viewDidLoad() {
super.viewDidLoad()
// do something
}
extend func viewDidAppear() {
// do something
} // <— the compiler should throw an error here.
}
// Example for replacing a function
class Geometry {
func volume() -> Double {
return 0;
}
}
class Cube: Geometry {
var length: Double = 0.0
replace func volume() -> Double {
let v = length * length * length
return v
}
}
Cheers,
Florian
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution