Overriding specific methods when adopting protocols with extension


(Iman Zarrabian) #1

Hi,
This is my first contribution to this list so I’m a little nervous.
I’ve been refactoring some code in one of our internal frameworks and noticed something I didn’t noticed about protocols before.
Maybe I’m missing the big picture here but I’ll expose the issue to you anyway.
Consider these protocols and classes declarations :

protocol Foo {
    func bar()
    func specificBar()
    func moreBar()
}

extension Foo {
    func specificBar() {
        print("default specificBar implementation")
    }
}

extension UIView: Foo {
    func bar() {
        print("uiview default bar")
        specificBar()
        moreBar()
    }
    
    func moreBar() {
        print("UIView is foo compliant and implements moreBar function")
    }
}

class CustomView: UIView {
    func startJob() {
        bar()
    }
    
    func specificBar() {
        print("CustomView specific bar implementation") //This is the implementation I want for specificBar but this is not the one picked at runtime.
    }
}

let view = CustomView()
view.startJob()

//Prints :
//uiview default bar
//default specificBar implementation
//UIView is foo compliant and implements moreBar function

I was wondering if it is a good idea to give the CustomView class the power to be more specific about it’s parent protocol adoption.

It seems to me that implementation of a protocol method cannot be easily changed by subclasses of the class that actually adopts the protocol in the first place. IMO one way to achieve the kind of specialization I’m trying to do is to create two protocols and another would be to implement a version of specificBar in the superclass (UIView here)

But does it make sense to consider some kind of cherry picking (with a new keyword) for those methods we want to implement more precisely than the one provided on the protocol extension?
Consider this new code for CustomView :

class CustomView: UIView {
    func startJob() {
        bar()
    }
    
    override adoption func specificBar() { //or override protocol => implements a method from a protocol adopted by the superclass
        print("CustomView specificBar implementation")
    }
}

let view = CustomView()
view.startJob()

//Would print :
//uiview default bar
//CustomView specificBar implementation
//UIView is foo compliant and implements moreBar function

I would appreciate your feedback.

···

--
Iman Zarrabian
@imanzarrabian


(Brian King) #2

Hey Iman, This is a known bug SR-103. It certainly has caught a few people
off guard. Dale Buckley is working on an evolution proposal that would
allow the bug to be fixed:

Proposal:
https://gist.github.com/dlbuckley/1858a7c0b5c027248fe16171d23ba01d

Conversation on the Proposal:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170313/033787.html

The only work around at this time is to make sure that your base class
implements all methods in the protocol.

Brian King

···

On Thu, Mar 23, 2017 at 11:15 AM, Iman Zarrabian via swift-evolution < swift-evolution@swift.org> wrote:

Hi,
This is my first contribution to this list so I’m a little nervous.
I’ve been refactoring some code in one of our internal frameworks and
noticed something I didn’t noticed about protocols before.
Maybe I’m missing the big picture here but I’ll expose the issue to you
anyway.
Consider these protocols and classes declarations :

protocol Foo {
    func bar()
    func specificBar()
    func moreBar()
}

extension Foo {
    func specificBar() {
        print("default specificBar implementation")
    }
}

extension UIView: Foo {
    func bar() {
        print("uiview default bar")
        specificBar()
        moreBar()
    }

    func moreBar() {
        print("UIView is foo compliant and implements moreBar function")
    }
}

class CustomView: UIView {
    func startJob() {
        bar()
    }

    func specificBar() {
        print("CustomView specific bar implementation") //This is the
implementation I want for specificBar but this is not the one picked at
runtime.
    }
}

let view = CustomView()
view.startJob()

//Prints :
//uiview default bar
*//default specificBar implementation*
//UIView is foo compliant and implements moreBar function

I was wondering if it is a good idea to give the CustomView class the
power to be more specific about it’s parent protocol adoption.

It seems to me that implementation of a protocol method cannot be easily
changed by subclasses of the class that actually adopts the protocol in the
first place. IMO one way to achieve the kind of specialization I’m trying
to do is to create two protocols and another would be to implement a
version of specificBar in the superclass (UIView here)

But does it make sense to consider some kind of cherry picking (with a new
keyword) for those methods we want to implement more precisely than the one
provided on the protocol extension?
Consider this new code for CustomView :

class CustomView: UIView {
    func startJob() {
        bar()
    }

    override adoption func specificBar() { //or override protocol =>
implements a method from a protocol adopted by the superclass
        print("CustomView specificBar implementation")
    }
}

let view = CustomView()
view.startJob()

//Would print :
//uiview default bar
*//CustomView specificBar implementation*
//UIView is foo compliant and implements moreBar function

I would appreciate your feedback.

--
Iman Zarrabian
@imanzarrabian

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


(Björn Forster) #3

Hi Brian,
is the override proposal still in the making?

Kind Regards,
Björn

···

On Thu, Mar 23, 2017 at 4:24 PM, Brian King via swift-evolution < swift-evolution@swift.org> wrote:

Hey Iman, This is a known bug SR-103. It certainly has caught a few people
off guard. Dale Buckley is working on an evolution proposal that would
allow the bug to be fixed:

Proposal:
https://gist.github.com/dlbuckley/1858a7c0b5c027248fe16171d23ba01d

Conversation on the Proposal:
https://lists.swift.org/pipermail/swift-evolution/
Week-of-Mon-20170313/033787.html

The only work around at this time is to make sure that your base class
implements all methods in the protocol.

Brian King

On Thu, Mar 23, 2017 at 11:15 AM, Iman Zarrabian via swift-evolution < > swift-evolution@swift.org> wrote:

Hi,
This is my first contribution to this list so I’m a little nervous.
I’ve been refactoring some code in one of our internal frameworks and
noticed something I didn’t noticed about protocols before.
Maybe I’m missing the big picture here but I’ll expose the issue to you
anyway.
Consider these protocols and classes declarations :

protocol Foo {
    func bar()
    func specificBar()
    func moreBar()
}

extension Foo {
    func specificBar() {
        print("default specificBar implementation")
    }
}

extension UIView: Foo {
    func bar() {
        print("uiview default bar")
        specificBar()
        moreBar()
    }

    func moreBar() {
        print("UIView is foo compliant and implements moreBar function")
    }
}

class CustomView: UIView {
    func startJob() {
        bar()
    }

    func specificBar() {
        print("CustomView specific bar implementation") //This is the
implementation I want for specificBar but this is not the one picked at
runtime.
    }
}

let view = CustomView()
view.startJob()

//Prints :
//uiview default bar
*//default specificBar implementation*
//UIView is foo compliant and implements moreBar function

I was wondering if it is a good idea to give the CustomView class the
power to be more specific about it’s parent protocol adoption.

It seems to me that implementation of a protocol method cannot be easily
changed by subclasses of the class that actually adopts the protocol in the
first place. IMO one way to achieve the kind of specialization I’m trying
to do is to create two protocols and another would be to implement a
version of specificBar in the superclass (UIView here)

But does it make sense to consider some kind of cherry picking (with a
new keyword) for those methods we want to implement more precisely than the
one provided on the protocol extension?
Consider this new code for CustomView :

class CustomView: UIView {
    func startJob() {
        bar()
    }

    override adoption func specificBar() { //or override protocol =>
implements a method from a protocol adopted by the superclass
        print("CustomView specificBar implementation")
    }
}

let view = CustomView()
view.startJob()

//Would print :
//uiview default bar
*//CustomView specificBar implementation*
//UIView is foo compliant and implements moreBar function

I would appreciate your feedback.

--
Iman Zarrabian
@imanzarrabian

_______________________________________________
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


(Brian King) #4

Hey Björn,
I haven't seen any conversation on this. The proposal looked to present 2
possible implementation approaches pretty well, and the feedback thread was
pretty light. Maybe someone from the core team can comment on the next step?

Since it is potentially source breaking, I hope it makes it into the Swift
4 release.

Brian

···

On Mon, May 8, 2017 at 9:33 AM, Björn Forster <bjoern.forster@googlemail.com > wrote:

Hi Brian,
is the override proposal still in the making?

Kind Regards,
Björn

On Thu, Mar 23, 2017 at 4:24 PM, Brian King via swift-evolution < > swift-evolution@swift.org> wrote:

Hey Iman, This is a known bug SR-103. It certainly has caught a few
people off guard. Dale Buckley is working on an evolution proposal that
would allow the bug to be fixed:

Proposal:
https://gist.github.com/dlbuckley/1858a7c0b5c027248fe16171d23ba01d

Conversation on the Proposal:
https://lists.swift.org/pipermail/swift-evolution/Week-of-
Mon-20170313/033787.html

The only work around at this time is to make sure that your base class
implements all methods in the protocol.

Brian King

On Thu, Mar 23, 2017 at 11:15 AM, Iman Zarrabian via swift-evolution < >> swift-evolution@swift.org> wrote:

Hi,
This is my first contribution to this list so I’m a little nervous.
I’ve been refactoring some code in one of our internal frameworks and
noticed something I didn’t noticed about protocols before.
Maybe I’m missing the big picture here but I’ll expose the issue to you
anyway.
Consider these protocols and classes declarations :

protocol Foo {
    func bar()
    func specificBar()
    func moreBar()
}

extension Foo {
    func specificBar() {
        print("default specificBar implementation")
    }
}

extension UIView: Foo {
    func bar() {
        print("uiview default bar")
        specificBar()
        moreBar()
    }

    func moreBar() {
        print("UIView is foo compliant and implements moreBar function")
    }
}

class CustomView: UIView {
    func startJob() {
        bar()
    }

    func specificBar() {
        print("CustomView specific bar implementation") //This is the
implementation I want for specificBar but this is not the one picked at
runtime.
    }
}

let view = CustomView()
view.startJob()

//Prints :
//uiview default bar
*//default specificBar implementation*
//UIView is foo compliant and implements moreBar function

I was wondering if it is a good idea to give the CustomView class the
power to be more specific about it’s parent protocol adoption.

It seems to me that implementation of a protocol method cannot be easily
changed by subclasses of the class that actually adopts the protocol in the
first place. IMO one way to achieve the kind of specialization I’m trying
to do is to create two protocols and another would be to implement a
version of specificBar in the superclass (UIView here)

But does it make sense to consider some kind of cherry picking (with a
new keyword) for those methods we want to implement more precisely than the
one provided on the protocol extension?
Consider this new code for CustomView :

class CustomView: UIView {
    func startJob() {
        bar()
    }

    override adoption func specificBar() { //or override protocol =>
implements a method from a protocol adopted by the superclass
        print("CustomView specificBar implementation")
    }
}

let view = CustomView()
view.startJob()

//Would print :
//uiview default bar
*//CustomView specificBar implementation*
//UIView is foo compliant and implements moreBar function

I would appreciate your feedback.

--
Iman Zarrabian
@imanzarrabian

_______________________________________________
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