Proposal: Add @requires_super attribute


(Vester Gottfried) #1

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


Add ability to make a call to super a requirement in subclass overrides
(Matthew Johnson) #2

+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@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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Marc Knaup) #3

+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@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@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@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


(Tino) #4

A huge +1 on this — I'd actually go one step further and propose to make it the default behavior:
Calling super rarely hurts, and it would be easier to find a better name for the attribute :wink: (maybe "replaceable"…)
Additionally, it is one step in the right direction for those who think "final" should be default (if there is any good reason to prefer final over requires_super, I haven't seen it yet).

Instead of enforcing the call to super, it would be possible to automatically run the super implementation after (or before) the overriding method (unless it is explicitly called).


(Andrey Tarantsov) #5

YES! +10.

'nough said.

One caveat: it should be syntactic, like other people mentioned; if nothing else, this will allow you to suppress the error when you know what you're doing.

A.


(TJ Usiyan) #6

I think that the problem with making it a default behavior is that you
can't be sure *when* to call super in a child implementation. you should
call in the middle for init but in the beginning for viewDidLoad and
(sometimes) at the end for dealloc.

···

On Wed, Dec 16, 2015 at 5:04 PM, Tino Heth via swift-evolution < swift-evolution@swift.org> wrote:

A huge +1 on this — I'd actually go one step further and propose to make
it the default behavior:
Calling super rarely hurts, and it would be easier to find a better name
for the attribute :wink: (maybe "replaceable"…)
Additionally, it is one step in the right direction for those who think
"final" should be default (if there is any good reason to prefer final over
requires_super, I haven't seen it yet).

Instead of enforcing the call to super, it would be possible to
automatically run the super implementation after (or before) the overriding
method (unless it is explicitly called).
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Etan Kissling) #7

Or simply make `throws` and `requires_super` mutually exclusive?

The case where the base class does not `throw` but the subclass `throws` isn't possible
as it would break all clients who cast everything to the base class and assume that it doesn't throw.

Etan

···

On 16 Dec 2015, at 17:46, Marc Knaup via swift-evolution <swift-evolution@swift.org> 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@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vester Gottfried) #8

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@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@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@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@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


(Marc Knaup) #9

Default behavior would require something like "unrequire" which seems odd.
Also this would break a lot of existing code and migration can't be done
automatically.

···

On Wed, Dec 16, 2015 at 11:04 PM, Tino Heth via swift-evolution < swift-evolution@swift.org> wrote:

A huge +1 on this — I'd actually go one step further and propose to make
it the default behavior:
Calling super rarely hurts, and it would be easier to find a better name
for the attribute :wink: (maybe "replaceable"…)
Additionally, it is one step in the right direction for those who think
"final" should be default (if there is any good reason to prefer final over
requires_super, I haven't seen it yet).

Instead of enforcing the call to super, it would be possible to
automatically run the super implementation after (or before) the overriding
method (unless it is explicitly called).
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Cullen MacDonald) #10

huge +1 from me.

···

On Wed, Dec 16, 2015 at 5:16 PM, Marc Knaup via swift-evolution < swift-evolution@swift.org> wrote:

Default behavior would require something like "unrequire" which seems odd.
Also this would break a lot of existing code and migration can't be done
automatically.

On Wed, Dec 16, 2015 at 11:04 PM, Tino Heth via swift-evolution < > swift-evolution@swift.org> wrote:

A huge +1 on this — I'd actually go one step further and propose to make
it the default behavior:
Calling super rarely hurts, and it would be easier to find a better name
for the attribute :wink: (maybe "replaceable"…)
Additionally, it is one step in the right direction for those who think
"final" should be default (if there is any good reason to prefer final over
requires_super, I haven't seen it yet).

Instead of enforcing the call to super, it would be possible to
automatically run the super implementation after (or before) the overriding
method (unless it is explicitly called).
_______________________________________________
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


(Marc Knaup) #11

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@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@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@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@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@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


(Tino) #12

Default behavior would require something like "unrequire" which seems odd.

the keyword for requires_super is so odd, it doesn't even fit in a single word! :wink:
I think it is much easer to find a word for something that can be replaced completely than for "you have to call the implementation of the parent class"

Also this would break a lot of existing code and migration can't be done automatically.

Two parts:
What is a lot? I really don't think calling super hurts in many places.
Why shouldn't it be possible to migrate automatically? It might get complicated for compiled libs, but definitely possible.


(Jordan Rose) #13

+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@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@gmail.com <mailto:vester.gottfried@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@knaup.koeln <mailto:marc@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@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Matthew Johnson) #14

Calling super asynchronously would not meet an @requires_super specification IMO. I would interpret it to mean you must call super before returning.

The compiler already guarantees all code paths return and guarantees subclass initializers call super. I don't think a sensible definition of @requires_super would be any more complex than that.

···

Sent from my iPad

On Dec 16, 2015, at 11:49 AM, Marc Knaup <marc@knaup.koeln> 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@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@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@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@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@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


(Marc Knaup) #15

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@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@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@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@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@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@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@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


(Javier Soto) #16

I'm not a fan of this feature because it encourages a type of API design
that's really hard to ensure that it's used correctly. The biggest problem
is the fact that often when a class expects or allows a method to be
overriden, and super needs to be called, it expects the call to happen in a
particular order: either before of after the implementation from the
subclass.

So yes, this is missing from Obj-C, yes, this is important because UIKit,
but going forward my feeling is that a language without this feature is a
language that will force you to think about an alternative way to implement
an API without this, and that'll probably be less error-prone.

···

On Wed, Dec 16, 2015 at 3:03 PM Tino Heth via swift-evolution < swift-evolution@swift.org> wrote:

Default behavior would require something like "unrequire" which seems odd.

the keyword for requires_super is so odd, it doesn't even fit in a single
word! :wink:
I think it is much easer to find a word for something that can be replaced
completely than for "you have to call the implementation of the parent
class"

Also this would break a lot of existing code and migration can't be done
automatically.

Two parts:
What is a lot? I really don't think calling super hurts in many places.
Why shouldn't it be possible to migrate automatically? It might get
complicated for compiled libs, but definitely possible.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Javier Soto


(Vester Gottfried) #17

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@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@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@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@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@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@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@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@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


(Matthew Johnson) #18

When a superclass method must be called either before or after the override it would be ideal to have the compiler synthesize the call rather than just verify the developer writes it. The developer should only need to write it when they need control over when that call happens.

willSet and didSet are pretty similar to this synthesis, but rather than synthesizing a call to super the compiler synthesizes the entire setter with the willSet and / or didSet code in the appropriate location(s).

···

On Dec 16, 2015, at 8:28 PM, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:

one solution is @requires_super(first|last). This cuts out "call me in the middle" but that is a worthwhile trade, in my opinion.

On Wed, Dec 16, 2015 at 9:22 PM, Javier Soto via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I'm not a fan of this feature because it encourages a type of API design that's really hard to ensure that it's used correctly. The biggest problem is the fact that often when a class expects or allows a method to be overriden, and super needs to be called, it expects the call to happen in a particular order: either before of after the implementation from the subclass.

So yes, this is missing from Obj-C, yes, this is important because UIKit, but going forward my feeling is that a language without this feature is a language that will force you to think about an alternative way to implement an API without this, and that'll probably be less error-prone.
On Wed, Dec 16, 2015 at 3:03 PM Tino Heth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Default behavior would require something like "unrequire" which seems odd.

the keyword for requires_super is so odd, it doesn't even fit in a single word! :wink:
I think it is much easer to find a word for something that can be replaced completely than for "you have to call the implementation of the parent class"

Also this would break a lot of existing code and migration can't be done automatically.

Two parts:
What is a lot? I really don't think calling super hurts in many places.
Why shouldn't it be possible to migrate automatically? It might get complicated for compiled libs, but definitely possible.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
--
Javier Soto
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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


(TJ Usiyan) #19

one solution is @requires_super(first|last). This cuts out "call me in the
middle" but that is a worthwhile trade, in my opinion.

···

On Wed, Dec 16, 2015 at 9:22 PM, Javier Soto via swift-evolution < swift-evolution@swift.org> wrote:

I'm not a fan of this feature because it encourages a type of API design
that's really hard to ensure that it's used correctly. The biggest problem
is the fact that often when a class expects or allows a method to be
overriden, and super needs to be called, it expects the call to happen in a
particular order: either before of after the implementation from the
subclass.

So yes, this is missing from Obj-C, yes, this is important because UIKit,
but going forward my feeling is that a language without this feature is a
language that will force you to think about an alternative way to implement
an API without this, and that'll probably be less error-prone.
On Wed, Dec 16, 2015 at 3:03 PM Tino Heth via swift-evolution < > swift-evolution@swift.org> wrote:

Default behavior would require something like "unrequire" which seems odd.

the keyword for requires_super is so odd, it doesn't even fit in a single
word! :wink:
I think it is much easer to find a word for something that can be
replaced completely than for "you have to call the implementation of the
parent class"

Also this would break a lot of existing code and migration can't be done
automatically.

Two parts:
What is a lot? I really don't think calling super hurts in many places.
Why shouldn't it be possible to migrate automatically? It might get
complicated for compiled libs, but definitely possible.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Javier Soto
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Tino) #20

The biggest problem is the fact that often when a class expects or allows a method to be overriden, and super needs to be called, it expects the call to happen in a particular order: either before of after the implementation from the subclass.

Do you have concrete examples for this claim?
Even if my impression that it doesn't matter in most cases is wrong, imho the argument is like advising not to wear a helmet on the construction site because it doesn't protect your feet.
Additionally, it can be easily addressed ("@prepend, @append"...)

So yes, this is missing from Obj-C, yes, this is important because UIKit, but going forward my feeling is that a language without this feature is a language that will force you to think about an alternative way to implement an API without this, and that'll probably be less error-prone.

Why?