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?
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.
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.
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. }
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.
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With