Explicit Protocol Conformance for Child Classes


(Arthur Ariel Sabintsev) #1

TL;DR: Force explicit protocol conformance of non-optional methods for
child classes on an opt-in basis.

Currently, a child class that inherits their parent class' protocol
conformations are not explicitly required to override their parent classes
implementation of a protocol. For example, a custom class,
MyTableViewController, does not explicitly have to override the
non-optional methods of the protocols (i.e., UITableViewDataSource,
UITableViewDelegate) to which UITableViewController conforms.

For many protocols, the superclass implementation of a protocol method may
be enough. Therefore, this feature should off by default, and only enabled
if the creator of the protocol requires it (for whatever reason). I suggest
using a new `@abstract` attribute to designate if a protocol requires
explicit conformance for children of a conforming parent class. This choice
of naming for the attribute is along the lines of what other languages call
an Abstract Class, which is what I'm trying to have added to Swift in this
fairly long-winded post.

@abstract protocol P: class {
     // All methods defined in here would need to be explicitly overridden
by the conforming class's children.
}

If you want to have optional methods in your protocol, then using the
@abstract attribute gets kind of messy, as you also have the @objc
attribute.

@abstract @objc protocol P: class {
     // All non-optional methods defined in here would need to be
explicitly overridden by the conforming class's children.
}

Thoughts?

Best,

Arthur / Sabintsev.com <http://sabintsev.com/>


(Jacob Bandes-Storch) #2

How about reusing the keyword "required" for this? It's already used (and
has a similar meaning) for initializers.

I think NSSecureCoding is a good example of a use case.

···

On Sat, Dec 12, 2015 at 9:14 AM, Arthur Ariel Sabintsev via swift-evolution <swift-evolution@swift.org> wrote:

TL;DR: Force explicit protocol conformance of non-optional methods for
child classes on an opt-in basis.

Currently, a child class that inherits their parent class' protocol
conformations are not explicitly required to override their parent classes
implementation of a protocol. For example, a custom class,
MyTableViewController, does not explicitly have to override the
non-optional methods of the protocols (i.e., UITableViewDataSource,
UITableViewDelegate) to which UITableViewController conforms.

For many protocols, the superclass implementation of a protocol method may
be enough. Therefore, this feature should off by default, and only enabled
if the creator of the protocol requires it (for whatever reason). I suggest
using a new `@abstract` attribute to designate if a protocol requires
explicit conformance for children of a conforming parent class. This choice
of naming for the attribute is along the lines of what other languages call
an Abstract Class, which is what I'm trying to have added to Swift in this
fairly long-winded post.

@abstract protocol P: class {
     // All methods defined in here would need to be explicitly overridden
by the conforming class's children.
}

If you want to have optional methods in your protocol, then using the
@abstract attribute gets kind of messy, as you also have the @objc
attribute.

@abstract @objc protocol P: class {
     // All non-optional methods defined in here would need to be
explicitly overridden by the conforming class's children.
}

Thoughts?

Best,

Arthur / Sabintsev.com <http://sabintsev.com/>

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


(Lily Ballard) #3

Seems to me this doesn't actually make sense on protocols at all. The
scenario of a base superclass like UITableViewController that conforms
to a protocol but only makes sense if its children override methods
doesn't actually have anything to do with the protocol at all, as it's
certainly not true any class that conforms to
UITableViewDelegate/DataSource wants subclasses to override methods,
that's only true of UITableViewController.

Given that, the proposed @abstract is actually something that would make
sense to put on the implementation of a method in a class, not on a
protocol. There's simply no such thing as an abstract protocol. And when
put on a method, it would probably be better to just call it
@requires_override, because that's all it means.

All that said, it doesn't actually make sense to put the attribute on
UITableViewController's methods either. And the reason for that is that
if you use a storyboard with static cells, you can have a
UITableViewController that functions perfectly fine without overriding
any of the UITableViewDelegate/DataSource methods. So requiring that a
subclass implement any of those methods would actually be wrong.

So overall, there are use-cases for a @requires_override attribute, but
UITableViewController actually isn't one of them (in fact, I don't think
anything in UIKit/Foundation qualifies).

Regarding `required`, that's not appropriate because `required` means
that every single descendant class must provide an implementation. And
it's only allowed on init methods because the whole point of `required`
is to remove the special-cased behavior of init for subclassing (e.g.
that it's not inherited by subclasses). There's no other place besides
init() where it makes sense to require every single descendant class to
provide an implementation because every other method will get inherited
(and even if your base class's implementation should always be
overridden, if your child overrides it, your grandchild certainly
doesn't have to!).

-Kevin Ballard

How about reusing the keyword "required" for this? It's already used
(and has a similar meaning) for initializers.

I think NSSecureCoding is a good example of a use case.

TL;DR: Force explicit protocol conformance of non-optional methods
for child classes on an opt-in basis.

Currently, a child class that inherits their parent class' protocol
conformations are not explicitly required to override their parent
classes implementation of a protocol. For example, a custom class,
MyTableViewController, does not explicitly have to override the non-
optional methods of the protocols (i.e., UITableViewDataSource,
UITableViewDelegate) to which UITableViewController conforms.

For many protocols, the superclass implementation of a protocol
method may be enough. Therefore, this feature should off by default,
and only enabled if the creator of the protocol requires it (for
whatever reason). I suggest using a new `@abstract` attribute to
designate if a protocol requires explicit conformance for children
of a conforming parent class. This choice of naming for the
attribute is along the lines of what other languages call an
Abstract Class, which is what I'm trying to have added to Swift in
this fairly long-winded post.

@abstract protocol P: class { // All methods defined in here
would need to be explicitly overridden by the conforming class's
children. }

If you want to have optional methods in your protocol, then using the
@abstract attribute gets kind of messy, as you also have the @objc
attribute.

@abstract @objc protocol P: class { // All non-optional methods
defined in here would need to be explicitly overridden by the
conforming class's children. }

Thoughts?

Best,

Arthur / Sabintsev.com[1]

_______________________________________________

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

Links:

  1. http://sabintsev.com/

···

On Sun, Dec 13, 2015, at 02:16 PM, Jacob Bandes-Storch via swift-evolution wrote:

On Sat, Dec 12, 2015 at 9:14 AM, Arthur Ariel Sabintsev via swift- > evolution <swift-evolution@swift.org> wrote:


(Etan Kissling) #4

Would maybe stick with @abstract or @deferred instead of the verbose @requires_override as the keyword.
Those keywords are known from other languages.

+1 with the rest, though.

It's really a pain to not have access to abstract classes.
My workaround for similar cases is
- Put function definitions with deferred implementation into protocols.
- Mark initializer of base class as private to prevent instantiation of the incomplete class.
- Put subclasses into same file as base class.
- In subclass, inherit from both the base class and the protocol, and override initializer as public.

Also agree with the irrelevance for UITableViewController. The class works perfectly fine without the overrides.

Etan

···

On 14 Dec 2015, at 00:27, Kevin Ballard via swift-evolution <swift-evolution@swift.org> wrote:

Seems to me this doesn't actually make sense on protocols at all. The scenario of a base superclass like UITableViewController that conforms to a protocol but only makes sense if its children override methods doesn't actually have anything to do with the protocol at all, as it's certainly not true any class that conforms to UITableViewDelegate/DataSource wants subclasses to override methods, that's only true of UITableViewController.

Given that, the proposed @abstract is actually something that would make sense to put on the implementation of a method in a class, not on a protocol. There's simply no such thing as an abstract protocol. And when put on a method, it would probably be better to just call it @requires_override, because that's all it means.

All that said, it doesn't actually make sense to put the attribute on UITableViewController's methods either. And the reason for that is that if you use a storyboard with static cells, you can have a UITableViewController that functions perfectly fine without overriding any of the UITableViewDelegate/DataSource methods. So requiring that a subclass implement any of those methods would actually be wrong.

So overall, there are use-cases for a @requires_override attribute, but UITableViewController actually isn't one of them (in fact, I don't think anything in UIKit/Foundation qualifies).

Regarding `required`, that's not appropriate because `required` means that every single descendant class must provide an implementation. And it's only allowed on init methods because the whole point of `required` is to remove the special-cased behavior of init for subclassing (e.g. that it's not inherited by subclasses). There's no other place besides init() where it makes sense to require every single descendant class to provide an implementation because every other method will get inherited (and even if your base class's implementation should always be overridden, if your child overrides it, your grandchild certainly doesn't have to!).

-Kevin Ballard

On Sun, Dec 13, 2015, at 02:16 PM, Jacob Bandes-Storch via swift-evolution wrote:

How about reusing the keyword "required" for this? It's already used (and has a similar meaning) for initializers.

I think NSSecureCoding is a good example of a use case.

On Sat, Dec 12, 2015 at 9:14 AM, Arthur Ariel Sabintsev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
TL;DR: Force explicit protocol conformance of non-optional methods for child classes on an opt-in basis.

Currently, a child class that inherits their parent class' protocol conformations are not explicitly required to override their parent classes implementation of a protocol. For example, a custom class, MyTableViewController, does not explicitly have to override the non-optional methods of the protocols (i.e., UITableViewDataSource, UITableViewDelegate) to which UITableViewController conforms.

For many protocols, the superclass implementation of a protocol method may be enough. Therefore, this feature should off by default, and only enabled if the creator of the protocol requires it (for whatever reason). I suggest using a new `@abstract` attribute to designate if a protocol requires explicit conformance for children of a conforming parent class. This choice of naming for the attribute is along the lines of what other languages call an Abstract Class, which is what I'm trying to have added to Swift in this fairly long-winded post.

@abstract protocol P: class {
     // All methods defined in here would need to be explicitly overridden by the conforming class's children.
}

If you want to have optional methods in your protocol, then using the @abstract attribute gets kind of messy, as you also have the @objc attribute.

@abstract @objc protocol P: class {
     // All non-optional methods defined in here would need to be explicitly overridden by the conforming class's children.
}

Thoughts?

Best,

Arthur / Sabintsev.com <http://sabintsev.com/>

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


(Arthur Ariel Sabintsev) #5

All,

I agree, the UITableViewController example was poor. I couldn't pull out
another example without being extremely abstract. I used UITableVC to
delineate the hierarchy more than to delineate the actual benefit of my
suggestion.

My goal, in one line, is to have the ability enforce certain
(marked/flagged) methods in a subclass to explicitly override their
parent's protocol-conformed methods. I chose @abstract as it's a known
keyword. Personally, @requires_override is my favorite suggestion thus far.

···

On Tue, Dec 15, 2015 at 9:43 AM Etan Kissling via swift-evolution < swift-evolution@swift.org> wrote:

Would maybe stick with @abstract or @deferred instead of the verbose
@requires_override as the keyword.
Those keywords are known from other languages.

+1 with the rest, though.

It's really a pain to not have access to abstract classes.
My workaround for similar cases is
- Put function definitions with deferred implementation into protocols.
- Mark initializer of base class as private to prevent instantiation of
the incomplete class.
- Put subclasses into same file as base class.
- In subclass, inherit from both the base class and the protocol, and
override initializer as public.

Also agree with the irrelevance for UITableViewController. The class works
perfectly fine without the overrides.

Etan

On 14 Dec 2015, at 00:27, Kevin Ballard via swift-evolution < > swift-evolution@swift.org> wrote:

Seems to me this doesn't actually make sense on protocols at all. The
scenario of a base superclass like UITableViewController that conforms to a
protocol but only makes sense if its children override methods doesn't
actually have anything to do with the protocol at all, as it's certainly
not true any class that conforms to UITableViewDelegate/DataSource wants
subclasses to override methods, that's only true of UITableViewController.

Given that, the proposed @abstract is actually something that would make
sense to put on the implementation of a method in a class, not on a
protocol. There's simply no such thing as an abstract protocol. And when
put on a method, it would probably be better to just call it
@requires_override, because that's all it means.

All that said, it doesn't actually make sense to put the attribute on
UITableViewController's methods either. And the reason for that is that if
you use a storyboard with static cells, you can have a
UITableViewController that functions perfectly fine without overriding any
of the UITableViewDelegate/DataSource methods. So requiring that a subclass
implement any of those methods would actually be wrong.

So overall, there are use-cases for a @requires_override attribute, but
UITableViewController actually isn't one of them (in fact, I don't think
anything in UIKit/Foundation qualifies).

Regarding `required`, that's not appropriate because `required` means that
every single descendant class must provide an implementation. And it's only
allowed on init methods because the whole point of `required` is to remove
the special-cased behavior of init for subclassing (e.g. that it's not
inherited by subclasses). There's no other place besides init() where it
makes sense to require every single descendant class to provide an
implementation because every other method will get inherited (and even if
your base class's implementation should always be overridden, if your child
overrides it, your grandchild certainly doesn't have to!).

-Kevin Ballard

On Sun, Dec 13, 2015, at 02:16 PM, Jacob Bandes-Storch via swift-evolution > wrote:

How about reusing the keyword "required" for this? It's already used (and
has a similar meaning) for initializers.

I think NSSecureCoding is a good example of a use case.

On Sat, Dec 12, 2015 at 9:14 AM, Arthur Ariel Sabintsev via > swift-evolution <swift-evolution@swift.org> wrote:

TL;DR: Force explicit protocol conformance of non-optional methods for
child classes on an opt-in basis.

Currently, a child class that inherits their parent class' protocol
conformations are not explicitly required to override their parent classes
implementation of a protocol. For example, a custom class,
MyTableViewController, does not explicitly have to override the
non-optional methods of the protocols (i.e., UITableViewDataSource,
UITableViewDelegate) to which UITableViewController conforms.

For many protocols, the superclass implementation of a protocol method may
be enough. Therefore, this feature should off by default, and only enabled
if the creator of the protocol requires it (for whatever reason). I suggest
using a new `@abstract` attribute to designate if a protocol requires
explicit conformance for children of a conforming parent class. This choice
of naming for the attribute is along the lines of what other languages call
an Abstract Class, which is what I'm trying to have added to Swift in this
fairly long-winded post.

@abstract protocol P: class {
     // All methods defined in here would need to be explicitly overridden
by the conforming class's children.
}

If you want to have optional methods in your protocol, then using the
@abstract attribute gets kind of messy, as you also have the @objc
attribute.

@abstract @objc protocol P: class {
     // All non-optional methods defined in here would need to be
explicitly overridden by the conforming class's children.
}

Thoughts?

Best,

Arthur / Sabintsev.com <http://sabintsev.com/>

_______________________________________________
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

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

--
Best,

Arthur / Sabintsev.com