This was an interesting swift problem I ran into. Consider the following class and protocol:
class Person {
}
protocol Parent where Self: Person {
func speak()
}
class GrandMotherPerson: Person, Parent {
func speak() {
print("I am a Grandmother Person")
}
}
class GrandFatherPerson: Person, Parent {
func speak() {
print("I am a Grandfather Person")
}
}
let gmp = GrandMotherPerson()
let gfp = GrandFatherPerson()
Now when you call
gmp.speak() // Output: I am a Grandmother Person
gfp.speak() // Output: I am a Grandfather Person
But if you cast to Parent
(gmp as Parent).speak() // EXC_BAD_ACCESS when it should say "I am a Grandmother Person"
but if I print(String(describing: gmp))
it says it's a __lldb_expr_226.GrandMotherPerson
Why can't swift call speak
on the class? If you remove the where Self: Person
from the protocol then it works as expected.
I'm pretty sure this is the same deep issue discussed at length at https://bugs.swift.org/browse/SR-55. Consider that this compiles and runs just fine:
class Person : NSObject {}
@objc protocol Parent where Self: Person {
func speak()
}
class GrandMotherPerson: Person, Parent {
func speak() {
print("I am a Grandmother Person")
}
}
let gmp = GrandMotherPerson()
let parent = gmp as Parent
parent.speak() // I am a Grandmother Person
But now delete @objc
and we get the same issue you're having:
class Person : NSObject {}
protocol Parent where Self: Person {
func speak()
}
class GrandMotherPerson: Person, Parent {
func speak() {
print("I am a Grandmother Person")
}
}
let gmp = GrandMotherPerson()
let parent = gmp as Parent
parent.speak() // EXC_BAD_ACCESS
So if it's the same issue, the Swift team are very well aware of it, but it runs deep and is difficult to fix. The workaround for now is to use @objc
as in my first example.
NOTE I have deliberately separated your last statement into two. That's because there seems to be a further issue with saying (gmp as Parent).speak()
- apparently we need an actual variable reference to the existential rather than an implicit temporary.
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