# 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()
Last Updated: 2/22/2020, 3:21:49 PM