Swift笔记:protocol(协议)

Swift笔记: protocol(协议)


概念简述

protocol = 协议
既然是协议,那么最基本的问题就是:
1. 协议规定了什么?(就像交通法规规定不能超速,不能闯灯之类的)
2. 谁来服从/遵守协议?(比如你在马路上跑,你就是交通法规的服从者)

一言以蔽之: ->服从协议的类至少需要实现协议中声明的属性和方法。<-
这包含了两层意思:
1. 协议的服从者是
2. 服从协议的类必须实现协议中声明的属性和方法,这个是没商量的。除此之外允许类再实现其他的属性和方法(听着像是继承父类的感觉,但这是有区别的,我们稍后再谈)


使用Protocol

文字堆完,来点实际的:如何使用协议?
使用协议只需要两个步骤:
1. 定义协议(先做到有法可依)
2. 让类服从协议

—>定义协议:

protocol ProtocalName {
    //协议内容
    func f1()->Int
    func f2(_ str: String)
    ..........
}

可以看出协议的定义和结构的定义类似:
1. 关键字是protocol
2. 仅仅是声明方法,而不需要实现

—>服从协议:

class ClassName: ProtocalName {
    //1. 实现自己的属性和方法
    .........

    //2. 实现ProtocalName协议中声明的属性和方法
    func f1()-> Int {
        ......
    }

    func f2(_ str: String) {
        ........
    }
}

让类服从协议也很简单,和类的继承语法相似。这个时候我们就说类ClassName服从于协议ProtocolName了
*服从协议的类 必须要实现协议中声明的属性和方法


栗子

为了加深理解,我们举个栗子

假设现在某地要举办一场运动会,运动会中同时举办的有跑步和游泳两个项目。
比赛前要检查选手的身份证,通过身份验证的选手方可参加比赛。

首先声明两个类: 类Runner和类Swimmer分别表示跑步运动员和游泳运动员,他们各自有一个方法(running和swimming)表示自己的技能。

class Runner {
    //Method
    func running() {
        print("I can run")
    }
}

class Swimmer {
    //Method
    func swimming() {
        print("I can swimming")
    }
}

比赛前一天,体育局给他们规定了一个协议,要求他们必须带身份证,第二天进场的时候必须出示身份证
于是就有了下面的协议:

//协议中声明了一个属性和一个方法
//服从这个协议的类必须实现showIDCard方法和name属性
protocol CarryIdCardProtocol {
    var name:String{get}
    func showIDCard()->Int
}

接下来让Runner类和Swimmer类 服从CarryIdCardProtocol协议

class Runner: CarryIdCardProtocol {
    func running() {
        print("I can run")
    }

    //实现CarryIdCardProtocol 协议规定的属性和方法
    //如果不实现协议中声明的东东,编译器会报错
    var name = "runnerZhang"
    func showIDCard() -> Int {
        //假设ID号是1
        return 1
    }
}

class Swimmer: CarryIdCardProtocol {
    func swimming() {
        print("I can swimming")
    }

    //实现CarryIdCardProtocol 协议规定的属性和方法
    //如果不实现协议中声明的东东,编译器会报错
    var name = "swimmerWan"
    func showIDCard() -> Int {
        //假设ID号是2
        return 2
    }
}

最后,神奇的地方来了! 协议还可以作为一种类型来使用
也就是说可以声明CarryIdCardProtocol类型的变量
函数可以接受CarryIdCardProtocol类型的参数

下面我们定义一个check( _ athlete: ICarryIdCardProtocol)函数,接受的就是CarryIdCardProtocol类型的参数,用以检查运动员身份

func check( _ athlete: CarryIdCardProtocol) {
    let athleteID = athlete.showIDCard()
    switch athleteID {
    case 1: print("\(athlete.name): Runner, Checked")
    case 2: print("\(athlete.name): Swimer, Checked")
    default: print("Unknow identification!")
    }
}

因为Swimmer类和Runner类都是服从于CarryIdCardProtocol协议的类,所以他们的对象可以作为CarryIdCardProtocol类型的参数传入check(_ :CarryIdCardProtocol)中

//创建对象
var swimmerWan = Swimmer()
var runnerZhang = Runner()

//检查运动员身份
check(swimmerWan)
check(runnerZhang)

对应的输出如下:

swimmerWan: Swimer, Checked
runnerZhang: Runner, Checked


Protocol 有什么用?

从上面的栗子中,你看到protocol的强悍之处了吗??
1. simmerWan和runnerZhang的类型不同,但是因为他们的类都服从于CarryIdCardProtocol协议,所以都可以作为check(: CarryIdCardProtocol)的参数传入
2. Swimmer类和Runner类都明明半毛钱关系都没有,可是都实现了name属性和showIDCard()方法,难道这是巧合? 不是的,是CarryIdCardProtocol协议逼他们的
3. 总之,当你想要逼迫某个类的实现某种功能,逼迫他提供某种服务的时候,不要犹豫,给他一个protocol,让他带上这个紧箍咒吧


Protocol VS 类继承

不论是语法还是功能,协议和继承是不是都怎么看怎么像,协议甚至还能像类一样继承! 协议和类似乎就是同一回事?

但其实他们是有本质区别的:
1. 协议只是声明了类必须要实现的属性和方法,其他的就交给类自己去实现。说白了就是给了个命令,其他啥也没有! 而类继承就不同了,父类给了子类无限的关怀,子类可以直接访问父类中允许访问的属性和方法,不需要子类再自己实现。
2. 类继承在一定程度上破坏了“低耦合”的要求,必然使父类和子类产生依赖关系。而协议就不同了,虽然Swimmer和Runner都服从CarryIdCardProtocol协议,都实现了name属性和showIDCard方法,但是,其实他们的属性和方法除了同名之外就没有什么关系了!

你可能感兴趣的:(Swift)