SLN SLN - 6 months ago 9
Swift Question

Error about protocol extension dispatching in a popular book Or I misunderstood?

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.

enter image description here

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

Answer

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