import UIKit
protocol someProtocol{
var mustBeSettable:Int {get set}
var doesNotNeedToBeSettable:Int{get}
static func someTypeMethod()//類方法
}//協議通常用var來聲明變量屬性,在類型聲明後加上{get set}來表示屬性是可讀可寫的,只讀屬性則用{get}來表示
protocol AnotherProtocol{
static var someTypeProperty:Int{get set}//類屬性
var fullName : String{get} //實例屬性
}//協議中定義類屬性時,總是使用static關鍵字作爲前綴。當協議的遵守者是類時,可以使用class或static關鍵字來聲明類屬性
protocol FullyNamed{
var fullName:String {get}
}
class StarShip:FullyNamed {
var prefix:String?
var name:String
init(name:String,prefix:String?=nil){
self.name=name
self.prefix=prefix
}
var fullName:String{
return (prefix != nil ? prefix!+" ":" ")+name
}
}
protocol RandomGenerator{
func random()->Double
}
class LinearGenerator:RandomGenerator {
var lastRandom = 42.0
let m = 139968.0
let a = 3877.0
let c = 29573.0
func random() -> Double {
lastRandom = ((lastRandom * a + c)%m)
return lastRandom/m
}
}
protocol Togglable{
mutating func toggle()
}//使用mutating關鍵字標記,表明當被調用時該方法將會改變協議遵循者實例的狀態
enum OnOffSwitch:Togglable{
case Off,On
mutating func toggle() {
switch self
{
case Off:
self = On
case On:
self = Off
}
}
}
protocol myProtocol{
init(someParameter:Int)
}
//required 修飾符只能用於修飾類初始化方法,表明這個類的每個子類都必須實現這個初始化方法
//當子類含有異於父類的初始化方法時(初始化方法的參數類型或參數數量),子類必須要實現父類的required初始化方法,並且也要使用required修飾符而不是override
//當子類沒有初始化方法時,可以不用實現父類的required初始化方法。
class myClass:myProtocol {
required init(someParameter: Int) {
//構造器實現
}
}
class Dice {
let sides:Int
let generator:RandomGenerator
init(sides:Int,generator:RandomGenerator){
self.sides=sides
self.generator=generator
}
func roll() -> Int{
return Int(generator.random()*Double(sides))+1
}
}
protocol DiceGame{
var dice:Dice{get}
func play()
}
protocol DiceGameDelegate{
func gameDidStart(game:DiceGame)
func game(game:DiceGame , didStartNewTurnRoll diceRoll:Int)
func gameDidEnd(game:DiceGame)
}//DiceGameDelegate協議可以用來追蹤DiceGame的遊戲過程
class SnakesAndLadders:DiceGame{
let finalSquare=25
let dice = Dice(sides: 6, generator: LinearGenerator())
var square = 0
var board : [Int]
init(){
board=[Int](count: finalSquare+1, repeatedValue: 0)
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, didStartNewTurnRoll: 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 numberOfTures = 0
func gameDidStart(game: DiceGame) {
numberOfTures = 0
if game is SnakesAndLadders{//檢查game是否是SnakesAndLadders類型的實例
print("Started a new game of Snakes and Ladders")
}
print("The game is using a \(game.dice.sides)")
}
func game(game: DiceGame, didStartNewTurnRoll diceRoll: Int) {
++numberOfTures
print("Rolled a \(diceRoll)")
}
func gameDidEnd(game: DiceGame) {
print("The game lasted for \(numberOfTures)")
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//協議
//協議規定了用來實現某一特定工作或者功能所必需的方法和屬性。類,結構體或枚舉類型都可以遵循協議,並提供具體實現來完成協議定義和功能。任意能夠滿足協議要求的類型被稱爲遵守這個協議
let ncc = StarShip(name: "DLG", prefix: "CHINA")
print(ncc.fullName)//CHINA DLG
//協議可以要求其遵循者實現某些指定的實例方法。這些方法作爲協議的一部分,像普通的方法一樣放在協議的定義中,但是不需要大括號和方法體。在協議的方法定義中,不支持參數默認值
let generator = LinearGenerator()
print("Here is a random number :\(generator.random())")
//Here is a random number :0.37464991998171
print("And anthor one: \(generator.random())")
//And anthor one: 0.729023776863283
//在協議中定義了一個方法旨在改變遵循該協議的實例,那麼在協議定義時需要在方法前加mutating關鍵字。這使得結構和枚舉遵循協議並滿足此方法要求
//注意 用類實現協議中的mutating方法時,不用寫mutating關鍵字;用結構體,枚舉實現協議中的mutating方法時必須寫mutating關鍵字
var lightSwitch :OnOffSwitch = OnOffSwitch.Off
print(lightSwitch)//Off
lightSwitch.toggle()
print(lightSwitch)//On
//協議構造器
//可以在遵循該協議的類中實現構造器,並指定其爲類的指定構造器或者便利構造器,在這兩種情況下,你都必須給構造器實現標上required修飾符
//協議類型
//儘管協議本身並不實現任何功能但是協議可以被當作類型來使用
//協議可以像其他普通類型一樣使用:
//作爲函數、方法或構造器中的參數類型或返回值類型
//作爲常量、變量或屬性的類型
//作爲數組、字典或其它容器中的元素類型
let d6 = Dice(sides: 6, generator: LinearGenerator())
for _ in 1...5{
print("Random dice roll is \(d6.roll())")
}
// Random dice roll is 3
// Random dice roll is 5
// Random dice roll is 4
// Random dice roll is 5
// Random dice roll is 4
//委託是一種設計模式,它允許類或結構體將一些需要他們負責的功能委託給其他的類型的實例。
let tracker = DiceGameTracker()
let game = SnakesAndLadders()
game.delegate=tracker
game.play()
// Started a new game of Snakes and Ladders
// The game is using a 6
// Rolled a 3
// Rolled a 5
// Rolled a 4
// Rolled a 5
// The game lasted for 4
//在擴展中添加協議成員
let ddd = Dice(sides: 12, generator: LinearGenerator())
print(ddd.textualDescription)
//A 12 -sided dice
//當一個類型已經實現了協議中的所有要求,卻沒有聲明爲遵守該協議時,可以通過擴展(空的擴展體)來補充協議聲明
let simonTheHamster=Hamster(name: "Simon")
let somethingTextRep:TextRepresentable=simonTheHamster
print(somethingTextRep.textualDescription)
//A hamster named Simon
}
}
extension Hamster : TextRepresentable {}
struct Hamster {
var name: String
var textualDescription:String{
return "A hamster named \(name)"
}
}
extension Dice : TextRepresentable{
var textualDescription : String{
return "A \(sides) -sided dice"
}
}
protocol TextRepresentable{
var textualDescription:String{get}
}