在《Swift ApprenticeBeginning programming with Swift 2.2》一书的第261~262页有一段关于协议(protocol)扩展的示例代码,如下所示
值gamesPlayed
在协议(protocol)TeamRecord
、协议(protocol)扩展和结构BaseballRecord
中定义
protocol TeamRecord {
var wins: Int { get }
var losses: Int { get }
var gamesPlayed: Int { get }
}
extension TeamRecord {
// gamesPlay#1
var gamesPlayed: Int {
return (wins + losses)
}
}
struct BaseballRecord: TeamRecord{
var wins: Int
var losses: Int
// gamesPlay#2
let gamesPlayed: Int = 162
}
let team1: TeamRecord = BaseballRecord(wins: 10, losses: 5)
let team2: BaseballRecord = BaseballRecord(wins: 10, losses: 5)
team1.gamesPlayed//The book claimed it will invoke "gamesPlay#1" (15)
team2.gamesPlayed//The book claimed it will invoke "gamesPlay#2" (162)
问题:根据书上的描述,team1调用的gamesPlayed
调用了协议(protocol)扩展中的实现(gamesPlay#1
);而 team2 调用的 gamesPlayed
调用 BaseballRecord
结构中的实现 (gamesPlay#2
)。
但 Xcode 7.3 Playground 告诉我一个不同的故事,team1.gamesPlayed
和 team2.gamesPlayed
都调用结构中的实现而不是协议(protocol)扩展。
问题 本书这部分的草率写法可能会误导我!如果不是,请纠正我。 (这里的图是从书中截取的)
非常感谢您的帮助和时间
额外人员:亲爱的 friend 们。如果你发现了这个问题并且也被同样的问题困扰,这里是我在向好心的帮助者学习后编写的简单的独立代码。只需将其复制并粘贴到您的 Xcode playground 中即可。希望这会对您有所帮助。
protocol MyProtocol {
func hardCasting()
}
extension MyProtocol {
func foo() {
print("Printing from the protocol extension")
}
func fooDefaul() {
print("Not implemented in type, I'm prented from the protocol extension")
}
func hardCasting() {
print("You shouldn't see this!!! YOU SHALL NOT PASS!")
}
}
struct MyType: MyProtocol {
func foo() {
print("Printing from the type")
}
func hardCasting() {
print("No matter what! I get only printed out by type!")
}
}
let lumi: MyProtocol = MyType()
lumi.foo()
lumi.fooDefaul()
let lumiProtocol: MyProtocol = MyType()
let lumiType: MyType = MyType()
lumiProtocol.hardCasting()
lumiType.hardCasting()
最佳答案
你是对的,这是书上的错误。如果方法是在协议(protocol)定义本身中声明的,则总是在协议(protocol)扩展之前选择具体实现。
但是,如果该方法是由协议(protocol)扩展添加的,没有在协议(protocol)定义中声明,并且也是在具体类型中实现的,您可以得到扩展的通过将具体类型转换为协议(protocol)来实现。
换句话说,如果示例代码包含以下内容:
protocol TeamRecord {
var wins: Int { get }
var losses: Int { get }
}
而不是这个:
protocol TeamRecord {
var wins: Int { get }
var losses: Int { get }
var gamesPlayed: Int { get }
}
那么书中的评论就是正确的。
这里有一个非常彻底的探索:
https://nomothetis.svbtle.com/the-ghost-of-swift-bugs-future
关于swift - 协议(protocol)扩展中的方法永远不会被调用,加上书中的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37711016/