这是我遇到的一个有趣的快速问题。请考虑以下类和协议:
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()
现在打电话
gmp.speak() // Output: I am a Grandmother Person
gfp.speak() // Output: I am a Grandfather Person
但是如果你转向父母
(gmp as Parent).speak() // EXC_BAD_ACCESS when it should say "I am a Grandmother Person"
但是如果我print(String(describing: gmp))
它说它是__lldb_expr_226.GrandMotherPerson
为什么不能在课堂上快速拨打speak
?如果从协议中删除where Self: Person
,则它会按预期工作。
答案 0 :(得分:6)
我很确定这是在https://bugs.swift.org/browse/SR-55详细讨论的同一个深层问题。考虑一下这个编译并运行得很好:
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
但现在删除@objc
,我们遇到了同样的问题:
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
因此,如果是同一个问题,Swift团队非常了解它,但它运行得很深,难以修复。现在的解决方法是在我的第一个示例中使用@objc
。
注意我故意将您的最后一个声明分成两部分。那是因为说(gmp as Parent).speak()
似乎还有一个问题 - 显然我们需要一个对存在主义而不是隐含临时性的实际变量引用。