swift中,協(xié)議是一種類型。協(xié)議可以有屬性、方法、構(gòu)造器,可以作為類型定義一個集合(數(shù)組、字典),可以繼承,也可以作為類型像普通類型一樣使用:
作為函數(shù)、方法和構(gòu)造器的參數(shù)類型,或者返回類型;
作為常量、變量和屬性的類型;
作為數(shù)組、字典和元組的元素類型。
協(xié)議語法
protocol SomeProtocol {
? ? // 這里是協(xié)議的定義部分
}
struct SomeStructure: FirstProtocol, AnotherProtocol {
? ? // 這里是結(jié)構(gòu)體的定義部分
}
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
? ? // 這里是類的定義部分
}
協(xié)議作為屬性要求
protocol SomeProtocol {
? ? var mustBeSettable: Int { get set }
? ? var doesNotNeedToBeSettable: Int { get }
} //用get、set來表示屬性可讀可寫,用get表示屬性可讀。沒有可寫不可讀的。
protocol AnotherProtocol {
? ? static var someTypeProperty: Int { get set }
} //static表示類型屬性要求
方法要求
protocol SomeProtocol {
? ? static func someTypeMethod()
}//static表示類方法要求,實例方法要求去掉static關(guān)鍵字
對于結(jié)構(gòu)體和枚舉的實例方法要求,需要加上mutating關(guān)鍵字
protocol Tooglable {
? ? mutating func toggle()
}
構(gòu)造器要求
protocol SomeProtocol {
? ? init(someParameter: Int)
}
遵循構(gòu)造器要求的類,如果沒有用final標記不會被繼承,則需要加required關(guān)鍵字確保所有子類也必須提供此構(gòu)造器實現(xiàn),從而也能符合協(xié)議。
protocol SomeProtocol {
? ? init()
}
class SomeSuperClass {
? ? init() {
? ? ? ? // 這里是構(gòu)造器的實現(xiàn)部分
? ? }
}
class SomeSubClass: SomeSuperClass, SomeProtocol {
? ? // 因為遵循協(xié)議,需要加上 required
? ? // 因為繼承自父類,需要加上 override
? ? required override init() {
? ? ? ? // 這里是構(gòu)造器的實現(xiàn)部分
? ? }
}
通過擴展來添加協(xié)議
某類或結(jié)構(gòu)體、或枚舉定義的時候沒有添加某一協(xié)議,后面添加協(xié)議用extension來標示,
protocol TextRepresentable {
? ? var textualDescription: String { get }
}
extension Dice: TextRepresentable {
? ? var textualDescription: String {
? ? ? ? return "A \(sides)-sided dice"
? ? }
}
為已定義的類Dice添加協(xié)議TextRepresentable。
協(xié)議的繼承
protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
? ? // 這里是協(xié)議的定義部分
}
檢查協(xié)議一致性
與檢查普通類型一致性一樣,也是用is,as?,as!。
委托(代理)模式
委托(代理)模式是指一個類或結(jié)構(gòu)體將一些功能委托給其它類的實例。swift的委托模式實現(xiàn)較簡單:定義協(xié)議來封裝那些需要被委托的功能,這樣就能確保遵循協(xié)議的類型能提供這些功能。
protocol DiceGame {
? ? var dice: Dice { get }
? ? func play()
}
protocol DiceGameDelegate {
? ? func gameDidStart(_ game: DiceGame)
? ? func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
? ? func gameDidEnd(_ game: DiceGame)
}
class SnakesAndLadders: DiceGame {
? ? let finalSquare = 25
? ? let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
? ? var square = 0
? ? var board: [Int]
? ? init() {
? ? ? ? board = [Int].init(repeating: 0, count: finalSquare + 1)
? ? ? ? //board = [Int](repeatElement(0, count: finalSquare + 1))
? ? ? ? board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
? ? ? ? board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
? ? }
? ? var delegate: DiceGameDelegate?
? ? func play() {
? ? ? ? ?square = 0
? ? ? ? delegate?.gameDidStart(self)
? ? ? ? gameLoop: while square != finalSquare {
? ? ? ? ? ? let diceRoll = dice.roll()
? ? ? ? ? ? delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
? ? ? ? ? ? switch square + diceRoll {
? ? ? ? ? ? case finalSquare:
? ? ? ? ? ? ? ? break gameLoop
? ? ? ? ? ? case let newSquare where newSquare > finalSquare:
? ? ? ? ? ? ? ? continue gameLoop
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? square += diceRoll
? ? ? ? ? ? ? ? square += board[square]
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? delegate?.gameDidEnd(self)
? ? }
}
class DiceGameTracker: DiceGameDelegate {
? ? var numberOfTurns = 0
? ? func gameDidStart(_ game: DiceGame) {
? ? ? ? numberOfTurns = 0
? ? ? ? if game is SnakesAndLadders {
? ? ? ? ? ? print("Started a new game of Snakes and Ladders")
? ? ? ? }
? ? ? ? print("The game is using a \(game.dice.sides)-sided dice")
? ? }
? ? func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
? ? ? ? numberOfTurns += 1
? ? ? ? print("Rolled a \(diceRoll)")
? ? }
? ? func gameDidEnd(_ game: DiceGame) {
? ? ? ? print("The game lasted for \(numberOfTurns) turns")
? ? }
}
let tracker = DiceGameTracker()
let game = SnakesAndLadders()
game.delegate = tracker
game.play()