当先锋百科网

首页 1 2 3 4 5 6 7

import Foundation


/


/


//_______________________________________________________________________________________________

//定义一个 Dice 类以备后用(协议做属性类型,协议做构造器参数类型)

class Dice{

    let sides: Int

    let generator: RandomNumberGenerator            //Dice 含有 sides generator 两个属性,前者用来表示骰子有几个面,后者为骰子提供一个随机数生成器,RandomNumberGenerator 协议做属性类型

    init(sides: Int, generator: RandomNumberGenerator){         //协议做构造器参数类型

        self.sides = sides

        self.generator = generator

    }

    func roll() -> Int{

        return Int(generator.random() * Double(sides)) + 1

    }

}

var d6 = Dice(sides: 6, generator: LinerCongruentialGenerator())

for _ in 1...5{

    println("Random dice roll is \(d6.roll())")

}


//***********************************************************************************************

//7.Delegation(委托代理模式)

//_______________________________________________________________________________________________

//委托是一种模式,它允许类或结构体将一些需要他们负责的功能交由给其他的类型

//委托模式的实现很简单:定义协议来封装那些需要被委托的函数和方法,使其遵循者拥有这些被委托的函数和方法


//_______________________________________________________________________________________________

//实例代码演示委托

protocol DiceGame{          //DiceGame 为实现游戏的协议

    var dice: Dice {get}

    func paly()

}

protocol DiceGameDelegate{      //DiceGameDelegate 为跟踪游戏过程

    func gameDidStart(game: DiceGame)

    func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)

    func gameDidEnd(game: DiceGame)

}


class SnakesAndLadders: DiceGame{                                           //定义 SnakesAndLadders 遵守协议 DiceGame

    let finalSquare = 25

    let dice = Dice(sides: 6, generator: LinerCongruentialGenerator())      //满足协议 DiecGame 的属性

    

    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[24] = -08

        board[14] = -10

        board[19] = -11

        board[22] = -02

    }

    var delegate: DiceGameDelegate?             //因为 delegate 是一个遵循 DiceGameDelegate 协议的可选属性类型,因此在 play()方法中使用了可选链来调用委托方法。若 delegate 属性为 nil, 则委托调用优雅地失效。若 delegate 不为nil,则委托方法被调用

    func paly(){                    //满足协议 DiceGame 的方法

        delegate?.gameDidEnd(self)          //通过代理使用 DiceGameDelegate 协议中的方法

        delegate?.game(self, didStartNewTurnWithDiceRoll: 1)

        delegate?.gameDidStart(self)

    }

}


class DiceGameTracker: DiceGameDelegate{        //DiceGameTracker 实现了 DiceGameDelegate 协议的方法要求

    var numberOfTurns = 0

    func gameDidStart(game: DiceGame) {         //满足协议 DiceGameDelegate 的方法

        if game is SnakesAndLadders{

            println("Started a new game of Snakes and Ladders")

        }

        println("The game is using a \(game.dice.sides) - sided dice")

    }

    func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll:Int){        //满足协议 DiceGameDelegate 的方法

            ++numberOfTurns

            println("Rolled a \(diceRoll)")

    }

    func gameDidEnd(game: DiceGame){                                            //满足协议的方法

            println("The game lasted for \(numberOfTurns) turns")

    }

}


let tracker = DiceGameTracker()

let game = SnakesAndLadders()

game.delegate = tracker             // SnakesAndLadders 类型的实例的 .delegate 赋值让它不为 nil 时,便可以在 SnakesAndLadders 实例中使用 DiceGameDelegate 协议内的方法

game.paly()


//***********************************************************************************************

//8.Adding Protocol Conformance with an Extension(在扩展中添加协议成员)

//_______________________________________________________________________________________________

//介绍

//即使无法修改源代码,依然可以通过扩展来扩充已存在类型


//_______________________________________________________________________________________________

//实例代码演示在扩展中添加协议成员

protocol TextRepresentable{     //定义一个协议

    func asText() -> String

}


extension Dice: TextRepresentable{          // Dice 协议扩展功能

        func asText() -> String{

        return "A \(sides) - side dice"

    }

}


let d12 = Dice(sides: 12, generator: LinerCongruentialGenerator())

println(d12.asText())           //这是我们可以使用扩展过后的协议的方法


//_______________________________________________________________________________________________

//通过扩展补充协议声明

struct Hamster{

    var name: String

    func asText() -> String{

    return "A hamster named \(name)"

    }

}

extension Hamster: TextRepresentable{}      //当一个类型已经实现了协议中的所有要求,却没有声明时,可以通过扩展来补充协议声明


let simonTheHamster = Hamster(name: "Simon")

let somethingTextRepresentable: TextRepresentable = simonTheHamster

println(somethingTextRepresentable.asText())


//***********************************************************************************************

//9.Collections of Protocol Types(集合中的协议类型)

//_______________________________________________________________________________________________

//协议可以被集合使用,表示集合中的元素均为协议类型

let things: [TextRepresentable] = [d12, simonTheHamster]

for thing in things{

    println(thing.asText())

}


//***********************************************************************************************

//10.Protocol Inheritance(协议的继承)

//_______________________________________________________________________________________________

//介绍

//协议能够继承一到多个其他的协议,语法与类的继承相似


//_______________________________________________________________________________________________

//实例代码演示协议的继承

protocol PrettyTextRepresentable: TextRepresentable{    //PrettyTextRepresentable 协议继承lTextRepresentable 协议,遵循 PrettyTextRepresentable 协议的同时,也需要遵循 TextRepresentable 的协议

    func asPrettyText() -> String

}


extension SnakesAndLadders: PrettyTextRepresentable {   //用扩展为 SnakesAndLadders 遵循PrettyTextRepresentable 协议

    func asPrettyText() -> String {             //遵守 PrettyTextRepresentable 协议中的方法

    var output = "Hello" + ":\n"

    for index in 1...finalSquare {

        switch board[index] {

            case let ladder where ladder > 0:

                output += "▲ "

            case let snake where snake < 0:

                output += "▼ "

            default:

                output += "○ "

            }

        }

        return output

    }

    func asText() -> String{                    //遵守 TextRepresentable 协议中的方法

            return "Listo"

    }

}

println(game.asPrettyText())

println(game.asText())


//***********************************************************************************************

//11.Protocol Composition(协议的合成)

//_______________________________________________________________________________________________

//实例代码演示协议的合成

protocol Named{             //Named 协议包含 String 类型的 name 属性

    var name: String {get}

}

protocol Aged{              //Aged 协议包含 Int 类型的 age 属性

    var age: Int {get}

}

struct Person1: Named, Aged{        //Person 结构体遵循了这两个协议

    var name: String

    var age: Int

}


func wishHappyBirthday(celebrator: protocol<Named, Aged>){      //wishHappyBirthday 函数的形参 celebrator 的类型为 protocol<Named,Aged>。可以传入任 意遵循这两个协议的类型的实例

    println("Happy birthday \(celebrator.name) - you're \(celebrator.age)")

}

let birthdayPerson = Person1(name: "Pin", age: 21)

wishHappyBirthday(birthdayPerson)


//***********************************************************************************************

//12.Checking for Protocol Conformance(检查协议的一致性)

//_______________________________________________________________________________________________

//使用 is 检查协议的一致性,使用 as 将协议类型向下转换为其他的协议类型(is 判断某个类型是否遵守协议,as? 返回一个可选值,当实例遵守协议时,返回协议类型,否则为 nilas 用以强制向下转化


//_______________________________________________________________________________________________

//实例代码演示检查协议的一致性

@objc protocol HasArea{     //这里的 @objc 用来表示协议是可选的,@objc 型协议只对类有效,只能检查类中协议的一致性

    var area: Double {get}

}

class Circle: HasArea {

    let pi = 3.1415927

    var radius: Double

    var area: Double {          //Circle 遵守协议 HasArea,并且把 area 写成计算型属性

        return pi * radius * radius

    }

    init(radius: Double) {

        self.radius = radius

    }

}

class Country: HasArea {        //Country 遵守协议 HasArea,并且把 area 写成存储型属性

    var area: Double

    init(area: Double) { self.area = area }

}

class Animal{                   //Animal 不遵守任何协议

    var legs: Int

    init(legs: Int) {

        self.legs = legs

    }

}


let objects: [AnyObject] = [    //CircleCountryAnimal 并没有相同的父类,所以使用 Anyobject 来装载他们的实例

    Circle(radius: 2.0),

    Country(area: 242_455),

    Animal(legs: 4)

]


for object in objects{

    if let objectWithArea = object as? HasArea{         //当数组中的元素遵循 HasArea 协议时,通过 as?操作符将其可选绑定(optional binding) objectWithArea 常量上

        println("Area is \(objectWithArea.area)")

    }

    else{

        println("Something that doesn't have an area")

    }

}


//***********************************************************************************************

//13.Optional Protocol Requirements(可选协议要求)

//_______________________________________________________________________________________________

//介绍

//可选协议含有可选成员,其遵循者可以选择是否实现这个可选成员,在协议中使用 @optional 关键字作为前缀来定义可选成员


//_______________________________________________________________________________________________

//实例代码演示可选协议的使用

@objc protocol CounterDataSource{

    @optional func incrementForCount(count: Int) -> Int     //定义协议可选方法

    @optional var fixedIncrement: Int {get}                 //定义协议可选属性

}

@objc class Counter{

        var count = 0

        var dataSource: CounterDataSource?

        func increment(){

            if let amount = dataSource?.incrementForCount?(count){      //由于 dataSource 可能为 nil,因此在 dataSource 后边加上了?标记来表明只在 dataSource 非空时才去调用 incrementForCount 方法,即使 dataSource 存在,但是也无法保证其是否实现了 incrementForCount 方法,因此在 incrementForCount 方法后边也加有?标记

                count += amount

            }

            else if let amount = dataSource?.fixedIncrement?{       // incrementForCount 不能被调用时,尝试使用可选属性 fixedIncrement 来代替(代理)

                count += amount

            }

        }

}


class ThreeSource: CounterDataSource{       //ThreeSource 实现了 CounterDataSource 协议

    let fixedIncrement = 3

}

var counter = Counter()

counter.dataSource = ThreeSource()      //使用 ThreeSource 作为数据源开实例化一个 Counter

for _ in 1...4{

    counter.increment()

    println(counter.count)

}


class TowardsZeroSource: CounterDataSource{         //TowardsZeroSource 实现了 CounterDataSource 协议中的 incrementForCount 方法

    func incrementForCount(count: Int) -> Int {

        if count == 0{

            return 0

        }

        else if count < 0{

            return 1

        }

        else{

            return -1

        }

    }

}

counter.count = -4

counter.dataSource = TowardsZeroSource()

for _ in 1...5{

    counter.increment()

    println(counter.count)

}