Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protocol extension method dispatch in Swift 2.0

I'm facing a problem regarding protocols methods dispatch.

I have a class hierarchy that looks like that:

protocol E {
    func test()
}

extension E {
    func test() {
        print("jello")
    }
}

class A: E {

}

class B: A {
    func test() {
        print("hello")
    }
}

But when I call test on an instance of class B statically forced to be typed A, "jello" gets printed, not "hello".

let b: A = B()  // prints "jello" not "hello"
b.test()

My understanding is that test method printing "jello" gets "integrated" into instances of A (since A conforms to E protocol). I'm then providing another implementation of test inside B (that inherits form A). I thought polymorphism would work here and calling test on B instance that are stored inside A references would print hello. What's happening here?

It's perfectly working when not using any protocol:

class A {
    func test() {
        print("jello")
    }
}

class B: A {
    override func test() {
        print("hello")
    }
}

let b: A = B() // prints "hello"
b.test() 

What's different from adopting a protocol that adds new methods to my parent class and providing a new implementation in a subclass, than having directly written this method in the parent class and then overriding it in a subclass?

Do you guys have any workaround?

like image 446
Nicolas B. Avatar asked Sep 23 '15 08:09

Nicolas B.


People also ask

What is extension protocol in Swift?

Protocols let you describe what methods something should have, but don't provide the code inside. Extensions let you provide the code inside your methods, but only affect one data type – you can't add the method to lots of types at the same time.

CAN protocol be extended Swift?

In Swift, you can even extend a protocol to provide implementations of its requirements or add additional functionality that conforming types can take advantage of. For more details, see Protocol Extensions. Extensions can add new functionality to a type, but they can't override existing functionality.

How do I create a Swift file extension?

Creating an extension in Swift When creating an extension, you add the word extension before the name. extension SomeNamedType { // Extending SomeNamedType, and adding new // functionality to it. }

Can we override protocol in Swift?

Here's the problem comes. An extension can't be overridden because the way Swift implement extension is using static dispatch which means its resolved at compile time.


1 Answers

Smells like a bug.

The only workaround I came up with was very ugly...

protocol E {
    func test()
}

func E_test(_s: E) {
    print("jello")
}

extension E {
    func test() { E_test(self) }
}

class A: E {
    func test() { E_test(self) }
}

class B: A {
    override func test() {
        print("hello")
    }
}

let b: A = B()
b.test()
like image 70
rintaro Avatar answered Sep 27 '22 17:09

rintaro