Search code examples
iosxcodeswiftpolymorphismxcode7

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?


Solution

  • 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()