protocol swift_swift-protocols - CSDN
  • protocolswift中的一种自定义约束,一般用于定义某些类的一种共同特性定义一个protocolprotocol Student { func getName() func getGrade()}某个class、struct、enum遵守这个约定,需要实现约定的方法(注意:...

    什么是Protocol?

    protocol是swift中的一种自定义约束,一般用于定义某些类的一种共同特性

    定义一个protocol

    protocol Student {

        func getName()

        func getGrade()

    }

    某个class、struct、enum遵守这个约定,需要实现约定的方法(注意:如果里面的方法有参数,不能有默认值)

    struct Person:Student {

        func getName() {

            print("my name")

        }   

        func getGrade() {

            print("my grade")

        }    

    }

     protocol中也可以定义属性,定义的属性必须制定该属性支持的操作(get、set)

    protocol PersonProtocol{

        var height:Int{get set}

        func getName()

        func getSex()

        func getgrade(name:String)

        func getAge(age:Int)

       // func getAge(age:Int = 0)  ❌ Default argument not permitted in a protocol method

    }

    height在protocol中是一个computed property,但在遵守该约定的类型中可以简单的定义成一个stored property
    当protocol中定义了一个只读属性,其实我们也可以在遵守该约定的类型中完成该属性的可读可写

    protocol PersonProtocol{

        var height:Int{get set}

        var weight:Int{get}

        func getName()

        func getSex()

        func getgrade(name:String)

        func getAge(age:Int)

    }

    struct Person:PersonProtocol {

        var height: Int = 178

        var weight: Int = 120

        func getName() {

            print("my name")

        }

        func getSex() {

            print("my sex")

        }

        func getgrade(name: String) {

            print("my grade")

        }

        func getAge(age: Int) {

            print("my age")

        }

    }

    var person1 = Person()

    person1.height   // 178

    person1.height = 189

    person1.height    // 189


    person1.weight    // 120

    person1.weight = 160

    // 当我们把person从Person转换成PersonProtocol时 他就是只读的了

    (person1 as PersonProtocol).weight = 160 //cannot assign to property: 'weight' is a get-only property




    展开全文
  • Swift笔记: protocol(协议) 概念简述 protocol = 协议 既然是协议,那么最基本的问题就是: 1. 协议规定了什么?(就像交通法规规定不能超速,不能闯灯之类的) 2. 谁来服从/遵守协议?(比如你在马路上...

    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中的protocol

    2017-08-16 23:39:43
    protocol作为swift中的一种自定义类型,和struct,class,enum不同,我们使用protocol来定义某种约定,而不是一个具体的类型。这种约定通常用于表示某些类型的共性

    作为swift中的一种自定义类型,和struct,class,enum不同,我们使用protocol来定义某种约定,而不是一个具体的类型。这种约定通常用于表示某些类型的共性

    注:本篇文章学习自泊学(boxueio.com)



    Protocol

    定义

    protocol Engine // 所有遵从Engine约定的类型都必须同时提供start和stop这两种方法。
    {
        // -3. 属性
        var cylinder: Int { get set } // 汽缸数 //  ①
        var capacity: Double {get} // 排量
        
        
        // -1. 方法
        func start()
        func stop()
        
        // -2. 参数:
    //    func getName(prefix: String = "")//  ② 默认参数在protocol中是不被允许的
        func getName(prefix: String)
        func getName()
    }

    注释:

    ①  由于Engine并不是一个具体的类型,因此当我们在一个protocol中定义具体属性的时候,我们必须使用{ get set }这样的方法来明确指定该属性支持的操作。{ get set }表示可读写的,{ get }表示只读

    ②  当protocol中的方法带有参数时,参数是不能有默认值的;如果要支持默认值,我们只能再定义两个方法


    应用

    1)由于Engine只是一个约定,因此不能直接生成安全的对象

    //let truck = Engine()

    2)只能定义一个具体类型的struct,class,enum,让它们遵从Engine的约定,如:

    class Truck: Engine {...}
    这和类继承的方式很像,但是 当冒号:后是一个protocol时,表示类型Truck遵从protocol Engine的约束。此时会报错,这是因为,虽然我们声明了Truck遵从Engine的约定,但是我们并没有真正实现start和stop这两个方法

    3)Protocol的继承

    除了定义属性和方法之外,protocol还可以继承的,用于表示约定A也是一个约定B,eg:

    protocol TurboEngine: Engine
    {
    //    var text: Int {get}
        func startTurbo()
        func stopTurbo()
    }
    let v8: TurboEngine
    表示v8不仅是一个TurboEngine,也是一个Engine


    自定义类型遵从Protocol

    1. 在自定义类型中实现Protocol中的方法

    Protocol中的方法必须全部实现

    class V8: TurboEngine{
        // ******** 方法约定 ********* 必须实现
        // ------ Engine methods -----
        func start() {
            print("Engine start")
        }
        func stop() {
            print("Engine stop")
        }
        func getName(prefix: String) {
            print("\(prefix)-v8-engine")
        }
        func getName() {
            print("v8-engine")
        }
        
        // ------- TurboEngine methods ------
        func startTurbo() {
            print("Turbo start")
        }
        func stopTurbo() {
            print("Turbo stop")
        }
    }


    2. 在自定义类型中实现Protocol中的属性

    Protocol中的属性也必须全部实现

    1)Protocol中可读写的属性

    class V8: TurboEngine{
        // ******** 属性约定 ********* 
        var cylinder = 8
    }
    
    cylinder在protocol Engine里看起来像个computed property,但是在V8的实现里可以简单定义为stored property
    let v8L40 = V8()
    v8L40.cylinder  // get
    v8L40.cylinder = 18 // set. 
    因此,一个stored property是满足protocol中get和set约定的


    2)Protocol中只读的属性

    class V8: TurboEngine{
        
        // V8实现的时候:
        // 1. 可以定义一个常量 让capacity达到只读的效果;
    //    let capacity = 4.0 // 不是必须的
        // 2. 让capacity在V8里面变成一个变量
    //    var capacity = 4.0
        // 3. 使用computed property来实现protocol里capacity的约定。当我们使用computed property的时候,通常需要定义一个内部的stored property,eg:
        private var innerCapacity = 4.0
        // 然后定义一个computed property来实现capacity的约定
        var capacity: Double {
            get {
                return self.innerCapacity
            }// 尽管在protocol里面,capacity只有get属性,但是在V8的实现里同样可以给它添加set方法
            
            set {
                self.innerCapacity = newValue
            }
        }
    }
    这样 当一个变量的类型是V8的时候,刚才添加的capacity就是可写的,eg:
    v8L40.capacity = 8.0

    但是如果把v8L40的类型转换成Engine或TurboEngine,capacity就会变成一个只读的


    3. 遵从多个Protocol

    在class的声明里使用 "," 将protocol分开 表示遵从多个约定

    class V8: TurboEngine, Motor{...}
    


    Protocol与Extension

    1. 为Protocol添加额外的默认功能

    protocol Flight{ // 航班信息
        var delay: Int { get } //  航班晚点的次数
        var normal: Int { get } // 航班正常的次数
        var flyHour: Int { get }// 航班飞行的总时长
    }
    1)拓展一个protocol 看似和拓展其他自定义类型没有太大的区别,

    都是使用extension关键字 + 要拓展的类型名字。

    extension Flight { // 和定义protocol不同,我们可以在一个protocol extension中提供默认的实现,eg:在这里可以把totalTrips定义成一个computed property
        var totalTrips: Int { return delay + normal } 
        func test ()->String{
            return "test"
        }
    }

    2)尽管此时我们还没有定义任何遵从Flight的约定,但是已经可以在extension中使用Flight的数据成员了,

    因为swift的编译器知道,任何一个遵从Flight的自定义类型 一定会定义Flight约定的各种属性。

    3)定义一个表示空客A380客机的类型:

    struct A380: Flight { // 遵从Flight protocol
        var delay: Int    // 添加Flight约定的三个属性
        var normal: Int
        var flyHour: Int
    }

    4)此时,当定义了一个A380对象之后,就可以使用totalTrips获取总的飞行次数了

    et a380 = A380(delay: 300, normal: 700, flyHour: 3 * 365 * 24)
    a380.totalTrips
    a380.test()
    playground:

    1000
    "test"


    2. 为已有的方法提供默认的实现

    protocol Flight{ // 航班信息
        var delay: Int { get } //  航班晚点的次数
        var normal: Int { get } // 航班正常的次数
        var flyHour: Int { get }// 航班飞行的总时长
        
    //     eg2:
        func delayRate() -> Double
    }
    extension Flight { 
        var totalTrips: Int { return delay + normal } 
        func test ()->String{
            return "test"
        }
        
        // eg2:
        func delayRate() -> Double {
            return Double(delay) / Double(totalTrips)
        }
    }
    a380.delayRate()

    3.  1和2的区别

    通过extension添加到protocol中的内容不算做protocol的约定

    1)在A380为delayRate添加一个自定义实现 ,让它返回0.1:

    struct A380: Flight { // 遵从Flight protocol
        var delay: Int    // 添加Flight约定的三个属性
        var normal: Int
        var flyHour: Int
        
        // eg3:
        func delayRate() -> Double {
            return 0.1
        }
    }

    a380.delayRate()
    (a380 as Flight).delayRate()
    这时 无论flight1的类型是A380 还是Flight,delayRate的结果都会是0.1。

    原因:我们在A380中重新定义了Flight中约定的方法


    2)注释掉在Flight中的delayRate方法:

    此时再次调用:

    a380.delayRate()
    (a380 as Flight).delayRate()
    flight1的类型是A380时,delayRate的结果是0.1;flight1的类型是Flight时,delayRate的结果是0.3。

    原因:此时delayRate不再是Flight约定的一部分了,在Flight extension中的delayRate只不过是为Flight protocol提供的一个方法1的添加的额外默认功能,既然delayRate不再是Flight约定的一部分了,那么swift编译器也不会认为A380中重定义的delayRate是在重新实现Flight中的约定,而只会把A380中的delayRate当成是普通方法,因此当我们把flight1的类型转换为Flight时,swift就会调用Flight的delayRate,事实上Flight的和A380中定义的delayRate没有任何关系。


    4. 为默认实现限定其可用的条件

    1)同时满足两个Protocol的类型,才可实现的方法

    2)eg:

    protocol OperationalLife{
        var maxFlyHours: Int { get }
    }

    3)然后使用extension来为同时满足Flight和OperationalLife这两个protocol类型添加一个新的方法

    extension Flight where Self: OperationalLife{
        func isInService() -> Bool {
            return self.flyHour < maxFlyHours
        }
    }
    1️⃣ 使用关键字where来表示额外的遵从条件
    2️⃣ 关键字Self用来表示遵从Flight类型,要求它必须同时遵从OperationalLife

    4)然后让A380遵从OperationalLife。

    extension A380: OperationalLife {
        var maxFlyHours: Int { return 18 * 365 * 24 }// 假定服务年限为18年
    }

    由于在extension里我们不能定义stored property,所以只能把maxFlyHours定义成一个computed property

    5)此时a380就可以使用OperationalLife中定义的isInService方法了

    a380.isInService()




    展开全文
  • swift中的protocol

    2018-04-17 17:25:25
    1、拉线就是赋值,给delegate和datasource赋值2、跟所有的面相protocol的编程一样,实现接口后,框架就会在指定的地方调用,客户的代码就会被执行。3、delegate的方法决定显示什么...

    1、拉线就是赋值,给delegate和datasource赋值

    2、跟所有的面相protocol的编程一样,实现接口后,框架就会在指定的地方调用,客户的代码就会被执行。

    3、delegate的方法决定显示什么


    展开全文
  • 注:来自斯坦福的Swift公开课 协议(Protocol)类似于C++中的一个声明的类,可基本表达为一个方法或变量的清单,但其中不包含任何的实现(a list of methods and vars with no implemention)。 一个协议由三个...
  • Swift3.0- 协议(protocol)代理,委托 /* * Protocol协议 (接口Interface或者纯虚函数) 协议用于统一方法和属性的名称,而不实现任何功能(使用代理设计模式) 协议能够被类、枚举、结构体实现,满足协议...
  • Swift3.0 protocol
  • Swift Protocol 详解 - 协议&面向协议编程 之前一个帖子我总结了自己秋招面试经历,作为一个Swift开发者,有一个非常高频的问题就是:你觉得Swift相比于其他语言(或者OC来说)的特点和优势是什么?作为一个见识...
  • 请求Protocol Buffers和JSON的Swift示例
  • 简要协议是苹果给它自己设计的语言的一种类型,Swift和OC都叫协议,它的功能更Java中的接口非常类似,其实就是Java中的接口功能,就是名称不一样而已,我们可以类比来学,但是有一点,Java中没有扩展,所以Java中的...
  • Swift语法的主要部分几乎相同的。当然也有通用的、运算符重载、ARC、补充倒闭之类的。 一、扩展(extension) 扩展 extension (类似OC中的分类, 但Swift中没有名字), 即在没有权限获取到原始代码的情况下,...
  • 而原生的swift中的 protocol里并没有可选项,所有定义的方法都是必须实现的,如果想要和OC一样的效果,需要在protocol 定义之前加上 @objc,使用没有@符号的 optional 关键字定义可选方法 @ob...
  • 前几天搞了object-c中使用ProtocolBuffer,今天尝试在swift中也使用该协议进行传输协议。 折腾了一上午终于搞定了,记录下在部署中所遇到的坑和自己实现的步骤。 1、安装protoc 命令和objectc安装方式是一样的,不...
  • OC中protocol是用weak和assign修饰的弱引用.Swiftprotocol功能被增强了,如果使用以下代码就会变成强引用.protocol TestDelegate { func cellClicked(let index:Int , let data:AnyObject); }class Test: NSObject...
  • Swift:Extension和Protocol

    2018-03-10 22:36:21
    一、Swift中的扩展功能(Extension)可以动态给类增加功能,类似于Javascript中的prototype;而在objective-c中,是通过runtime来实现动态调用或者添加功能的。定义方式如下:extension SomeType { }1. 单位转换...
  • 在 OC 中想要定义一个变量是某个类的实例,并且遵守了若干 Protocol 很容易实现,比如: SomeClass&lt;Protocol01, Protocol02&gt; *instance = ... 在 Swift 中如果想要实现同样的效果应该怎么办呢?...
  • swift推出一年多了,断断续续学了一些,一直没有真正引入自己的项目中。 最近准备做一个 Today Extension,恰好是一个... 尤其是swift和objc的interoperability,最简单、也是困扰我时间最长的就是protocol中的optio
  • swift中定义一个protocol相比objective-c来说,要更加简单,我们只需要通过一下方法就可以定义一个protocol:定义不包含optional方法的protocolprotocol XXXXXXDelegate : NSObjectProtocol { func XXXXXXX()//代理...
  • protocol CommonTrait: class { func commonBehavior() -> String } extension CommonTrait { func commonBehavior() -> String { return "from protocol extension" } ...
  • protocol(协议)用户统一方法和属性的名称,而不实现任何功能,我相信很多学过ios的对protocol都不会陌生,swift中的protocol不仅定义方法还能定义属性。本文简单的实现了swift协议方法的具体方法,只是想记载一下,...
1 2 3 4 5 ... 20
收藏数 9,611
精华内容 3,844
关键字:

protocol swift