Reputation: 5082
At page 261 ~ 262 of the book "Swift ApprenticeBeginning programming with Swift 2.2" there is a sample code about protocol extension is shown as follow
the value gamesPlayed
is defined in the protocol TeamRecord
, the protocol extension and the structure 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)
Problem: According to the description of the book, the gamesPlayed
called by team1 invokes the implementation in the protocol extension (gamesPlay#1
); while the gamesPlayed
called by team2 invokes the implementation (gamesPlay#2
) in the BaseballRecord
structure.
But the Xcode 7.3 playground told me a different story, both team1.gamesPlayed
and team2.gamesPlayed
invokes the implementation in the structure rather than the protocol extension.
Question I might be misled by the sloppy writing of this part of the book! If not, please correct me. (the picture here is captured from the book)
Thanks a lot for your kind help and time
Extra Staff: Dear friends. In case you found this question and also bothered by the same issue, here comes the simple self-contained code I wrote after I learned from the kind helpers. Just copy and paste it into your Xcode playground. Hope this will help you a bit.
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()
Upvotes: 3
Views: 94
Reputation: 13679
You are correct, this is an error in the book. Concrete implementations are always selected before a protocol extension if the method is declared in the protocol definition itself.
However, if the method is added by protocol extension, is not declared in the protocol definition, and is also implemented in a concrete type, you can get the extension's implementation by casting the concrete type to the protocol.
In other words, if the sample code had included this:
protocol TeamRecord {
var wins: Int { get }
var losses: Int { get }
}
instead of this:
protocol TeamRecord {
var wins: Int { get }
var losses: Int { get }
var gamesPlayed: Int { get }
}
then the comments in the book would be correct.
There's a very thorough exploration of this here:
https://nomothetis.svbtle.com/the-ghost-of-swift-bugs-future
Upvotes: 2