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}
}