天天看點

20.Swift學習之協定

協定

協定為方法、屬性、以及其他特定的任務需求或功能定義一個

大緻的架構

。協定可被類、結構體、或枚舉類型采納以提供所需功能的具體實作。滿足了協定中需求的任意類型都叫做遵循了該協定。

協定的定義

  • 協定的定義方式與類,結構體,枚舉的定義都非常相似
protocol SomeProtocol {
    // 屬性
    // 方法
}
           
  • 協定中的屬性
    • 不可以有預設值
    • 必須設定是

      {get}

      或者

      {get set}

      ,注意:get與set之間是沒有逗号的
    • 必須設定為var
  • 協定中的方法
    • 可以定義普通方法也可以是

      mutating

      方法
    • 方法不能有方法體
    • 方法的參數不可以有預設值
protocol Pet {
    // 定義屬性
    var name: String {get set}
    var age: Int {get}
    // 定義方法
    func feed(food: String)
    mutating func shout(sound :String);
}
           

協定的遵守格式(實作協定)

  • 格式
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
    // 類的内容
    // 實作協定中的方法
}
           
  • 實作協定中的屬性
    • 此時屬性可以設定預設值
    • 協定中屬性為可讀可寫的,可以直接聲明為var類型就可以
    • 協定中屬性為可讀屬性,可以直接聲明為let類型就可以,也可以聲明為var類型
  • 實作協定中的方法
    • 可以為方法中的參數設定預設值
    • 在結構體中,如果需要改變自身的值,需要在方法前面加mutating關鍵字。在協定的方法中添加mutating關鍵字,如果結構體來遵守協定,需要有mutating這個關鍵字,如果是類來遵守協定,mutating關鍵字就不需要了。
class Cat : Pet{
    //屬性可以設定預設值
    //可讀可寫用var
    var name: String = "Dingding"
    //隻讀可以用let
    let age: Int = 10
    func feed(food: String) {
        print("feed\(food)")
    }
    //方法參數可以有預設值
    //類實作mutating方法要修改屬性值時必須加不用加mutating
    func shout(sound: String = "miaomiao") {
        self.name = "Caicai"
        print("shout\(sound)")
    }
}

struct Dog : Pet{
    var name: String
    var age: Int
    func feed(food: String) {
        print("feed\(food)")
    }
    //結構體實作mutating方法要修改屬性值時必須加mutating
    mutating func shout(sound: String) {
        self.name = "Guaiguai"
        print("shout\(sound)")
    }
}
           
  • 協定之間的繼承
protocol CrazySportProtocol {
    func jumping()
}
//繼承協定
protocol SportProtocol : CrazySportProtocol {
    func playBasketball()
    func playFootball()
}
//此時的類必須所有方法都實作
class Person:SportProtocol{
    func playBasketball() {
        print("playBasketball")
    }    
    func playFootball() {
        print("playFootball")
    }    
    func jumping() {
        print("jumping")
    }
}
           

協定中方法的可選

方法一
  • 定義協定
@objc protocol SportProtocol2 {
     // 該方法可選
    @objc optional func playBasketball()
    func playFootball()
}
           
  • 遵守協定
class Person : SportProtocol2 {
    var name : String?
    var age : Int = 0
    // 實作協定中的方法,此時可以不實作協定中的可選方法,當然也可以實作
    func playBasketball() {
        print("人在打籃球")
    }
}
           
方法二

擴充協定

protocol SomeProtocol {
    func requiredFunc()
    func optionalFunc()
}

extension SomeProtocol {
    func optionalFunc() {
      print("optionalFunc擴充中實作")
    }
}

class SomeClass: SomeProtocol {
    func requiredFunc() {
      print("requiredFunc具體類中實作")
    }
}
           

協定的運用——代理模式

//1.定義一個協定,規定需要完成的任務
protocol BuyTicketProtocol {
    func buyTicket()
}
           
//2.讓具體的類或者結構體實作協定,将任務具體化
class Assist : BuyTicketProtocol{
    func buyTicket() {
        print("助手去買票")
    }
}

class HN : BuyTicketProtocol{
    func buyTicket() {
        print("黃牛去買票")
    }
}
           
//3.委托方申明一個屬性(遵循協定),然後在真正需要完成任務的時候調用屬性來完成
class Person {
    // 1.定義協定屬性
    var delegate : BuyTicketProtocol

    // 2.自定義構造函數
    init (delegate : BuyTicketProtocol) {
        self.delegate = delegate
    }

    // 3.行為
    func goToBeijing() {
        print("找代理買票")
        delegate.buyTicket()
        print("拿到票去北京")
    }
}
           
let p = Person(delegate: HN())
p.goToBeijing()
let p2 = Person(delegate: Assist())
p2.goToBeijing()