zoukankan      html  css  js  c++  java
  • Swift学习笔记十六:协议

    Protocol(协议)用于统一方法和属性的名称,而不实现不论什么功能。

    协议可以被类。枚举。结构体实现。满足协议要求的类,枚举,结构体被称为协议的遵循者
    遵循者须要提供协议指定的成员,如属性,方法,操作符,下标等。

    一、协议的基本的语法

         咱们还是先上代码吧

    protocol Human {
        var name:String{ get set }
        var isMan:Bool{set get}
        class var isUsable:Bool { set get }  //类成员。表示这个类是否可用
        func ageDescription(ages:Int...)     //函数參数能够是变长參数
    }
    class Student{
        var name = ""
    }
    class PrimaryStudent:Student,Human{
        class var isUsable:Bool{
            get{    return self.isUsable    }
            set{    self.isUsable = newValue    }
        }
        var isMan:Bool
        init(name:String,isMan:Bool){
            self.isMan = isMan
            super.init()
            self.name = name
        }
        func ageDescription(ages:Int...){
            var ageCount = 0
            for age in ages{
                ageCount += age;
            }
            println("this man age is (ageCount)")
        }
    }


    重点:
         ① 遵守某个协议须要像继承一样。在:后面加入这个协议
         ② 假设既要继承又要遵守协议,须要把继承的父类放在最前面
         ③ 对于协议中的属性,须要标明属性的读写类型,能够是读写或者仅仅读(不能仅仅写不读)
         ④ 对于类成员,须要在协议中的属性前面加classkeyword,假设是类遵守协议加classkeyword,假设是枚举或者结构体遵守协议加statickeyword
         ⑤ 协议中方法支持变长參数,但不支持參数默认值

    二、协议类型
         虽然协议本身并不实现不论什么功能,可是协议能够被当做类型来使用。
    使用场景:
    协议类型作为函数、方法或构造器中的參数类型或返回值类型
    协议类型作为常量、变量或属性的类型
    协议类型作为数组、字典或其它容器中的元素类型

    protocol RandomNumberGenerator {
        func random() -> Double
    }
    class Dice {
        let sides: Int
        let generator: RandomNumberGenerator
        init(sides: Int, generator: RandomNumberGenerator) {
            self.sides = sides
            self.generator = generator
        }
        func roll() -> Int {
            return Int(generator.random() * Double(sides)) + 1
        }
    }
    
    class LinearCongruentialGenerator: RandomNumberGenerator {
        func random() -> Double {
            return random()%10.0
        }
    }
    var d6 = Dice(sides: 6,generator: LinearCongruentialGenerator())

    解释:
         在Dice中。generator是RandomNumberGenerator协议类型。

    所以仅仅能使用遵守RandomNumberGenerator协议的类、结构体、枚举类型给他赋值。在后面我们能够看到,在初始化的时候使用遵守RandomNumberGenerator协议的LinearCongruentialGenerator给他赋值了

    三、托付代理模式
         玩过Objective-C的朋友相比对托付代理非常熟悉了,Swift中的托付代理和OC的大同小异,我们还是来看看代码吧

    protocol NameComplete {
        func nameSetCompleted(theName:String)
    }
    class Student{
        var delegate:NameComplete?
        var name:String{
        didSet{
            self.delegate?.nameSetCompleted(name)
        }
        }
        init(name:String,delegate:NameComplete){
            self.name = name
            self.delegate = delegate
        }
        
    }
    class DoSth:NameComplete{
        func nameSetCompleted(theName:String){
            println("name:(theName) is set ")
        }
    }
    var a = DoSth()
    var b = Student(name:"",delegate:a)
    b.name = "小笨狼"  //输出:name:小笨狼 is set

    解释:
         NameComplete是一个代理。DoSth遵从并实现这个代理,Student调用代理。

    在Student中name被赋值之后,代理中nameSetCompleted方法会被调用
         
    三、可选协议
         玩过OC的朋友知道。OC中协议有的方法是可选的。在Swift中协议也有这个功能,以下我们来看看

    @objc protocol Human{
        @optional var name:String{get set}
        @optional func descript()
    }
    class Student:Human{
        var name:String = "abc"
        func descript(){
        println("abc")
        }
    }

    重点:
         ① 对于可选方法或者属性。须要在方法或者属性前加上@optionalkeyword
         ② 假设协议中含有可选方法或者属性,在定义协议时须要在protocol 前加上@objckeyword
         ③ 在可选协议中,不能出现OC没有的类型。比方变长类型
         ④ 可选协议仅仅能被类遵从

    四、协议继承
         协议和类一样。也能够继承

    protocol pName{
        var name:String{set get}
    }
    protocol dName:pName{
        func descript()
    }
    class Human:dName{
        var name = ""
        func descript(){
            println(name)
        }
    }

    解释:
         dName继承了pName,所以dName协议不仅含有一个descript方法还含有name属性,所以遵从dName协议的类必须有name属性和descript方法

    五、协议合成

    protocol Named {
        var name: String { get }
    }
    protocol Aged {
        var age: Int { get }
    }
    struct Person: Named, Aged {
        var name: String
        var age: Int
    }
    func wishHappyBirthday(celebrator: protocol<Named, Aged>) {
        println("Happy birthday (celebrator.name) - you're (celebrator.age)!")
    }
    let birthdayPerson = Person(name: "Malcolm", age: 21)
    wishHappyBirthday(birthdayPerson)   //输出Happy birthday Malcolm - you're 21!

    解释:
         wishHappyBirthday方法传入的參数是<NamedAged>合成协议类型,这时能够传入遵从这2个协议的结构体的实例
         注意:
              协议合成并非生成一个新协议。而是多个协议合成一个暂时协议,超出范围后就会失效




  • 相关阅读:
    2015腾讯暑期实习笔试题目
    二叉树的优点和缺点
    pandas对象保存到mysql出错提示“BLOB/TEXT column used in key specification without a key length”解决办法
    事务的隔离机制
    Flink Sink定制开发
    Presto实现定时从配置文件读取配置
    LDAP与Sentry API使用
    Presto压测报告
    PrestoSPI安全扩展
    项目重构总结
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5326538.html
Copyright © 2011-2022 走看看