協議

  1. 協議語法
protocol protocol1 {
    
}

protocol protocol2 {
    
}

class Test {
    
}

class Test1: Test, protocol1, protocol2 {
    
}
  1. 屬性要求
    1. 一定是var關鍵子的屬性
    2. 屬性的名字要一致
    3. 屬性的類型要一致
    4. 如果協議是get只讀屬性,那麼協議的實現可以是隻讀屬性,也可以是可讀寫屬性。
    5. 如果協議是get,set屬性,那麼協議的實行必須是可讀寫屬性。
protocol FullName {
    var fullName: String {get}
}

class Person: FullName {
    var name: String
    var preName: String?
    init(name: String, preName: String? = nil) {
        self.name = name
        self.preName = preName
    }
    
    var fullName: String {
        var str = preName ?? ""
        if str.isEmpty {
            str = name
        }else{
            str = str + " " + name
        }
        return str
    }
}

let a = Person(name: "小明", preName: "王")
print(a.fullName)
  1. 方法要求
    1. 協議可以定義實例方法或者類型方法,類型方法必須用static關鍵字。
    2. 協議的遵循者要實現相應的實例方法或者類型方法,類型方法可以用static,class關鍵字
    3. 有參數就在協議裏寫上參數,有返回值就寫上返回值,沒有就不寫。
protocol Funcation {
    func sum(one: Double, two: Double) -> Double
    static func addOne(num: Int) -> Int
}

class Test: Funcation {
    func sum(one: Double, two: Double) -> Double {
        return one + two
    }
    
    static func addOne(num: Int) -> Int {
        return num + 1
    }
}
  1. 異變方法要求
    1. 協議要在func前用mutating關鍵字修飾。
    2. 協議實現如果是值類型(枚舉類型,結構體)也要用mutating修飾。如果是類就不需要這個關鍵字了。
protocol ChangeProtocol {
    mutating func change()
}

enum Switch: String, ChangeProtocol {
    case on, off
    mutating func change() {
        switch self {
        case .on:
            self = .off
        case .off:
            self = .on
        }
    }
}

class Test: ChangeProtocol {
    func change() {
        
    }
}

var a = Switch.on
a.change()
print(a)
  1. 構造器要求
protocol SomeProtocol {
    init()
}

class SomeClass {
    init() {
        
    }
}

class SubSomeClass: SomeClass, SomeProtocol {
   required override init(){
        
    }
}

class SubSomeClass1: SomeProtocol {
    required init(){
        
    }
}

class SubSomeClass2: SubSomeClass1 {
    required init(){
        
    }
}
  1. 可失敗構造器要求
    1. 協議中定義了可失敗構造器,那麼協議的遵守者可以實現非可失敗構造器,也可以實現可失敗構造器。
    2. 協議中定義了不可失敗構造器,那麼協議的遵守者要用非可失敗構造器去實現。
protocol SomeProtocol {
    init?()
}

class SomeClass: SomeProtocol {
   required init() {
        
    }
    
//    required init()? {
//
//    }
}
  1. 協議作爲類型
import UIKit

protocol RandomNum {
    func random() -> Double
}

struct Dice {
    var sides: Int
    var random: RandomNum
    init(sides: Int, random: RandomNum) {
        self.sides = sides
        self.random = random
    }
    
    func roll() ->  Int{
        return Int(self.random.random() * Double(self.sides)) + 1
    }
}

struct RandomStruct: RandomNum {
    func random() -> Double {
        let Y = arc4random_uniform(100 - 0) + 0
        return Double(Y % 10) * 0.1
    }
}

let dice = Dice(sides: 6, random: RandomStruct())
print(dice.roll())
  1. 委託
//1. 委託
protocol RandomDevice {
    func roll() -> Double
}

class Dice {
    var sides: Int
    var randomDevice: RandomDevice
    init(sides: Int, randomDevice: RandomDevice) {
        self.sides = sides
        self.randomDevice = randomDevice
    }
    
    func playDiceOnce() -> Int {
        return Int(randomDevice.roll() * Double(sides)) + 1
    }
}

class LineRandomDevice: RandomDevice {
    func roll() -> Double {
        return Double((arc4random_uniform(100 - 0) + 0) % 10) * 0.1
    }
}


protocol DiceGame {
    var dice: Dice {get}
    func play()
}

protocol DiceGameTrack {
    func diceGameDidStart(diceGame: DiceGame)
    func diceGamePlay(diceGame: DiceGame, number: Int)
    func diceGameDidEnd(diceGame: DiceGame)
}

class SnakesAndLaddersGame: DiceGame {
    var finalStep = 25
    var board: [Int]
    var delegate: DiceGameTrack?
    var squire = 0
    
    init() {
        board = Array(repeating: 0, count: finalStep + 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 dice: Dice = Dice(sides: 6, randomDevice: LineRandomDevice())
    func play() {
        self.delegate?.diceGameDidStart(diceGame: self)
        loop: while squire != finalStep {
            let number = dice.playDiceOnce()
            self.delegate?.diceGamePlay(diceGame: self, number: number)
            switch number + squire{
            case finalStep:
                break loop
            case let newValue where newValue > finalStep:
                continue loop
            default:
                squire += number
                squire += board[squire]
            }
        }
        self.delegate?.diceGameDidEnd(diceGame: self)
    }
}

class SnakesAndLaddersDiceGameTrack: DiceGameTrack {
    var turns = 0
    func diceGameDidStart(diceGame: DiceGame) {
        print("\(diceGame) is starting")
    }
    
    func diceGamePlay(diceGame: DiceGame, number: Int) {
        turns += 1
        print("\(diceGame) roll is \(number) playing...")
    }
    
    func diceGameDidEnd(diceGame: DiceGame) {
        print("\(diceGame) is end  \(turns)turns")
    }
}

var a = SnakesAndLaddersGame()
var b = SnakesAndLaddersDiceGameTrack()
a.delegate = b
a.play()
  1. 通過擴展來遵守協議
//2. 通過擴展遵守協議
protocol Despration {
    func despration()
}

extension SnakesAndLaddersGame: Despration {
    func despration() {
        print("fineSquire is \(self.finalStep)")
    }
}
a.despration()
  1. 有條件的遵守協議
    1. 數組中map方法 $0代表每個元素。最後map方法返回一個元素自定義的數組。
    2. 數組中的joined方法,只有當數組中的每個元素都是String類型纔可以使用。
//3. 有條件的遵循協議
extension Dice: Despration {
    func despration() -> String{
        return "A \(sides)-sided dice"
    }
}
extension Array: Despration where Element: Despration {
    func despration() -> String{
        let itemsAsText = self.map { $0.despration() }
        return ("[" + itemsAsText.joined(separator: ", ") + "]")
    }
}

var d6 = Dice(sides: 6, randomDevice: LineRandomDevice())
var d12 = Dice(sides: 12, randomDevice: LineRandomDevice())
let myDice = [d6, d12]
print(myDice.despration())
  1. 空遵守
    1. 當一個類型寫了所有協議的實現,滿足了這個協議的所有要求,但是沒有顯式的遵守,這時候是不遵守的。
    2. 這個時候我們可以通過擴展將這個類型遵守這個協議並且大括號裏不寫內容。
protocol Description {
    var description:String{get}
    func test() -> String
}

struct Test{
    var name: String
    var description: String{
        return "name is \(name)"
    }
    
    func test() -> String {
        return "test"
    }
}

extension Test:Description{}

var a = Test(name: "小明")
print(a.description)

var b: Description = a
print(b.test())
  1. 協議類型集合
protocol Description {
    var description: String{get}
}

class Animal: Description {
    var description: String{
        return "Animal type"
    }
}

class Dog: Description {
    var description: String{
        return "Dog type"
    }
}

var a: [Description] = [Animal(), Dog()]
for item in a {
    print(item.description)
}
  1. 協議的繼承
protocol Description {
    var description: String{get}
}

protocol Test: Description {
    var test: String{get}
}

class Animal: Test {
    var description: String{
        return "Animal type"
    }
    var test: String{
        return "test"
    }
}

var aAnimal = Animal()
print(aAnimal.test)
print(aAnimal.description)
  1. 類專屬協議
protocol Description {
    var description: String{get}
}

protocol Test: AnyObject, Description {
    var test: String{get}
}

//下邊結構體將會報錯
struct Dog: Test {
    var description: String{
        return "Dog type"
    }
    var test: String{
        return "test"
    }
}

class Animal: Test {
    var description: String{
        return "Animal type"
    }
    var test: String{
        return "test"
    }
}

var aAnimal = Animal()
print(aAnimal.test)
print(aAnimal.description)
  1. 協議合成
protocol Name {
    var name: String{get}
}

protocol Age {
    var age: Int{get}
}

struct Person: Name, Age {
    var name: String
    var age: Int
}

func description(person: Name & Age){
    print("name is \(person.name)   age is \(person.age)")
}

description(person: Person(name: "小明", age: 23))
  1. 判斷是遵守了哪種協議
    1. as? : 用來判斷是否遵守了某個協議,如果沒遵守就返回nil,如果遵守了,就返回這個協議。
    2. as!和 as?一樣但是有可能觸發運行時錯誤。
protocol AreaProtocol {
    var area: Double {get}
}

class Circle: AreaProtocol {
    let pi = 3.1415926
    var ridus: Double
    var area: Double {
        return pi * ridus * ridus
    }
    
    init(ridus: Double) {
        self.ridus = ridus
    }
}

class Country: AreaProtocol {
    var area: Double
    init(area: Double) {
        self.area = area
    }
}

class Animal {
    var legs: Int
    init(legs: Int) {
        self.legs = legs
    }
}


var objs: [AnyObject] = [
    Circle(ridus: 5.0),
    Country(area: 1300),
    Animal(legs: 4)
]

for item in objs {
    if let areaPro = item as? AreaProtocol {
        print("area = \(areaPro.area)")
    }else{
        print("no area")
    }
}
  1. 可選協議要求
    1. @objc用在協議前面
    2. @objc optional用在屬性和方法前面
    3. 這種表明只有oc的類纔可以遵守該協議。
import UIKit

@objc protocol CountDataSource {
    @objc optional func incerment(count: Int) -> Int
    @objc optional var countIncerment: Int{get}
}

class Count {
    var total = 0
    var dataSource: CountDataSource?
    func increment(){
        if let amount = dataSource?.incerment?(count: total){
            total += amount
        }else if let amount = dataSource?.countIncerment{
            total += amount
        }
    }
}

class CountObj: NSObject, CountDataSource{
    var countIncerment: Int{
        return 3
    }
}

//var a = Count()
//a.dataSource = CountObj()
//for _ in 1...4 {
//    a.increment()
//    print(a.total)
//}


class  ZeroSource: NSObject, CountDataSource {
    func incerment(count: Int) -> Int {
        switch count {
        case 0:
            return 0
        case let cot where cot > 0:
            return -1
        case let cot where cot < 0:
            return 1
        default:
            return 0
        }
    }
}

var b = Count()
b.dataSource = ZeroSource()
b.total = -4

for _ in 1...5{
    b.increment()
    print(b.total)
}
  1. 協議的擴展
    1. 可以給協議擴展計算屬性,和方法。
    2. 被擴展的協議是可選的協議了,在類裏面可以直接使用。
import UIKit
protocol TestProtocol {
    func random() -> Double
}

extension TestProtocol {
    var probability: Bool {
        return random() >= 0.5
    }
}

class TestClass: TestProtocol {
    func random() -> Double {
        let num = arc4random_uniform(100 - 0) + 0
        let count = Double(num % 10) * 0.1
        print(count)
       return count
    }
}

var a = TestClass()
print(a.probability)
  1. 爲協議擴展添加約束條件
extension Collection where Element: Equatable{
    func allEqual() -> Bool {
        for item in self {
            if item != self.first {
                return false
            }
        }
        return true
    }
}

var a = [1,1,1,1,1]
var b = [1,1,1,1,1]
var c = [1,1,1,1,1,2]

print(a.allEqual())
print(b.allEqual())
print(c.allEqual())
  1. 總結
    1. as
      1. as用來向上轉型,如dogObj as Animal
      2. as用來消除可選類型的警報,如dogObj as Any
    2. as?
      1. 用來向下轉型,animalObj as?Dog。
      2. 用來判斷是否遵守某個協議,areaObj as? AreaProtocol
    3. as!
      1. 用來向下轉型,animalObj as?Dog。可能觸發運行時錯誤
      2. 用來判斷是否遵守某個協議,areaObj。可能觸發運行時錯誤
    4. is
      1. 用來判斷某個對象是否屬於某個類,dogObj is Dog
    5. == 判斷是否兩個值相當, === 判斷是否兩個引用是同一個地址。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章