SLN
SLN

Reputation: 5082

The method in the protocol extension is never get called, plus, an error in the book

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

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

Answers (1)

Daniel Hall
Daniel Hall

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

Related Questions