Swift 2.0: Pitfalls mixing protocol extensions and inheritance

This post refers to Swift 2.0, beta 6:

Protocol extensions are great to provide default behavior for a protocol. But beware. They expose some dangerous traits when used in combination with inheritance.

//: Playground

import UIKit

protocol Winable:class {
    func win() -> String
}

extension Winable {
    func win() -> String {
        return ("You won")
    }
}

class BattleDelegate:Winable  {
    func win() -> String {
        return ("You won this battle")
    }
}

class EpicBattleDelegate:BattleDelegate {
    override func win() -> String {
        return ("You won this epic battle.")
    }
}

class LotteryDelegate:Winable {
}

class LotteryBigPrizeDelegate:LotteryDelegate {
    func win() -> String {
        return ("You won the big prize")
    }
}

class Game {
    weak var delegate:Winable?

    init (delegate:Winable) {
        self.delegate = delegate
        print (self.delegate?.win())
    }
}

let commonBattleGame = Game(delegate:BattleDelegate())
//prints "Optional("You won this battle.")"
let extraordinaryBattleGame = Game(delegate:EpicBattleDelegate())
//prints "Optional("You won this epic battle.")"

let commonLotteryGame = Game(delegate: LotteryDelegate())
//prints "Optional("You won")"
let extraordinaryLotteryGame = Game(delegate: LotteryBigPrizeDelegate())
//prints "Optional("You won")

My assumption was that LotteryBigPrizeDelegate would print:

"Optional("You won the big prize")

Well. I was wrong. I didn’t win the big prize.

Conclusion: If you want to subclass your next fancy class that conforms to a protocol with an extension be careful: You have to implement all protocol functions the subclass wants to change in the root class, too. If you don’t your subclass won’t be able to override the protocol’s standard behavior defined in the extension.

Note: Everything would work fine if I would instantiate LotteryBigPrizeDelegate with the type „LotteryBigPrizeDelegate“ instead of „Winable“. But that would defy the notion of using a delegate protocol at all, wouldn’t it?

Update: @jckarter states „Protocol extensions can’t extend a class method table. The subclass method shadows the extension method.“

Dieser Beitrag wurde unter Mac veröffentlicht. Setze ein Lesezeichen auf den Permalink.

Schreib einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *