[Draft Proposal] Improve protocol inheritance behaviour


(Dale Buckley) #1

So I did consider using the 'override' keyword, but it then raised the
question as to what should happen when 'super' is called.

I agree that by adding 'override' it makes it more obvious that you are
overriding an existing implementation of the method, regardless of if it's
defined in the class you are inheriting from or from the protocol
extension. But if you add 'override' you are explicitly saying you can call
the super implementation.

So the question is what should happen here? Realistically you could expect
calling 'super' would call the protocol extension implementation of the
method, but I'm trying to think of the problems that could occur if its
implemented in that way.

Any thoughts on this?

Dale


(Dale Buckley) #2

So having a little more of a think about this what should happen in this
situation:

class A {
    func method() {
        print("A")
    }
}

protocol P {
    func method()
}

extension P {
    func method() {
        print("P")
    }
}

class B: A, P {
    override func method() {
        super.method()
        print("B")
    }
}

B().method()

When 'super' is called by the method in class B, should it call the method
in class A or the protocol extension in extension P? As it stands by using
override it always looks to it's superclass and ignores what happens in the
protocol extension. This says to me that the 'override' keyword isn't right
for solving this issue and should be reserved for inheritance, and not for
solving this issue with choosing the subclass implementation over the
protocol extension implementation.

Dale

···

On Tue, Mar 14, 2017 at 11:39 AM, Dale Buckley <dalebuckley86@gmail.com> wrote:

So I did consider using the 'override' keyword, but it then raised the
question as to what should happen when 'super' is called.

I agree that by adding 'override' it makes it more obvious that you are
overriding an existing implementation of the method, regardless of if it's
defined in the class you are inheriting from or from the protocol
extension. But if you add 'override' you are explicitly saying you can call
the super implementation.

So the question is what should happen here? Realistically you could expect
calling 'super' would call the protocol extension implementation of the
method, but I'm trying to think of the problems that could occur if its
implemented in that way.

Any thoughts on this?

Dale


#3

The way I want things to work, “super” always calls the superclass’s method
with matching name and signature.

For the scenario you outlined, the superclass defines such a method, so it
gets called. For the situation relevant to this proposal, if the superclass
*obtains* such a method via default implementation of a protocol
requirement, I want exactly the same thing to happen.

Namely, when the subclass’s override calls “super”, I want the
superclass’s method with identical name and signature to be invoked. It
does not matter where the superclass *got* that method, all that matters is
the superclass *has* such a method, in which case it gets called.

Nevin


(Dale Buckley) #4

Thats the thing, I believe it does matter where the super implementation is
called from so the developer can reasonably reason as to what behaviour
they are invoking by calling 'super'. Because of this I'm not 100%
convinced that this is the right way to go, even if on face value it seems
like the logical way to do it. It's only when digging in that it becomes
apparent that there could be issues in moving this direction.

I'm starting to wonder if there is a third option here, something that
still explicitly defines that you are taking control over the
implementation of the protocol required method implementation but without
taking the 'override' keyword and making it do something that it's not
originally intended to do (primarily used for overriding methods in the
parent class).

I would quite like a few other people to join in on this discussion so we
can get a few minds at work (not that I don't value you opinion Nevin, I
really do, just think the more minds the better) on this problem as it is a
legitimate one that I would quite like to see solved by the time Swift 4
rolls around. Any takers?

Dale

···

On Tue, Mar 14, 2017 at 11:55 AM, Dale Buckley <dalebuckley86@gmail.com> wrote:

So having a little more of a think about this what should happen in this
situation:

class A {
    func method() {
        print("A")
    }
}

protocol P {
    func method()
}

extension P {
    func method() {
        print("P")
    }
}

class B: A, P {
    override func method() {
        super.method()
        print("B")
    }
}

B().method()

When 'super' is called by the method in class B, should it call the method
in class A or the protocol extension in extension P? As it stands by using
override it always looks to it's superclass and ignores what happens in the
protocol extension. This says to me that the 'override' keyword isn't right
for solving this issue and should be reserved for inheritance, and not for
solving this issue with choosing the subclass implementation over the
protocol extension implementation.

Dale

On Tue, Mar 14, 2017 at 11:39 AM, Dale Buckley <dalebuckley86@gmail.com> > wrote:

So I did consider using the 'override' keyword, but it then raised the
question as to what should happen when 'super' is called.

I agree that by adding 'override' it makes it more obvious that you are
overriding an existing implementation of the method, regardless of if it's
defined in the class you are inheriting from or from the protocol
extension. But if you add 'override' you are explicitly saying you can call
the super implementation.

So the question is what should happen here? Realistically you could
expect calling 'super' would call the protocol extension implementation of
the method, but I'm trying to think of the problems that could occur if its
implemented in that way.

Any thoughts on this?

Dale