Swift超基础语法(协议与代理篇)

作者: S_Lyu | 来源:发表于2016-08-03 00:01 被阅读737次

    代理设计模式是开发中比较常见的设计模式之一,那么在Swift中应该如何实现代理与协议呢?

    协议(protocol)

    • 协议用于定义一些函数的声明,并要求其他类来实现这个函数的具体内容,概念与OC无异,有些类似Java中的接口
    • apple不建议开发者在Swift中的协议里定义"可选实现的函数",并且Swift协议中的函数默认都是必须实现的,这是为了保证Swfit这门语言的严谨性
    • Swift协议中必须实现的函数如果不实现则直接编译报错(这与OC这样的弱语言不同)

    定义协议的格式

    编写协议的格式:
    protocol 协议名字 : 基协议 {  //当然也可以不遵守基协议
        //方法的声明
    }
    
    例:定义一个买票的协议
    protocol buyTicketProtocol {
        func buyTicket() -> Void
    }
    
    Tips:
    如果一个协议继承了基协议NSObjectProtocol,那么遵守这个协议的类也必须要继承NSObject这个类
    

    遵守协议的格式

    一个类若要遵守一个协议,只需要在自己所继承的父类后面写上要遵守的协议名并以逗号","隔开,如果这个类无需继承,那么直接在冒号后面写上协议的名字就好

    遵守协议的格式:
    class Person : NSObject,SportProtocol{}
    
    例:定义一个会买票的黄牛类
    class Tout : buyTicketProtocol {  //无继承类遵守协议
        func buyTicket() {
            print("here's your ticket")
        }
    }
    
    Tips:
    Swift中的基协为NSObjectProtocol,这与OC中的基协议(NSObject)有些不同
    

    协议的继承

    • 上面有提到,当我们自定义一个协议的时候可以选择让这个协议继承自NSObjectProtocol,不单单如此,自定义的协议也可以遵守另外一个协议哦,基本格式如下:
    protocol showTicketNumberProtocol {  //展示票号
        func showTicketNumber() -> Void
    }
    protocol buyTicketProtocol : showTicketNumberProtocol  {  //买票
        func buyTicket() -> Void
    }
    
    • 如果一个类遵循了一个含有继承的协议,那么这个类就必须实现这个协议链中所有的必须实现的函数,否则编译报错
    class Tout : buyTicketProtocol  { 
        func buyTicket() {
            print("here's your ticket")
        }
        func showTicketNumber() {  //必须实现buyTicketProtocol所继承的"父"协议中的函数
            print("123456")
        }
    }
    
    Tips:
    上面提到的"如果一个协议继承了基协议NSObjectProtocol,那么遵守这个协议的类也必须要继承NSObject这个类"
    这是因为我们需要NSObject这个父类来帮我们实现NSObjectProtocol中定义的函数,否则编译器会以"没有实现NSObjectProtocol中的函数为由而报错"
    

    协议中可选实现的函数

    为了保证Swift语言的严谨性,不建议在协议中定义可选实现的函数,不过不建议不代表不能嘛,我们可以利用OC特性来实现在Swift协议中定义可选实现函数

    • 创建带有OC特性的协议
    @objc  //表示一下代码含有OC特性
    protocol showTicketNumberProtocol {
        optional func showTicketNumber() -> Void  //optional修饰的函数为可选择实现(或不实现)的函数
    }
    
    • 遵守带有OC特性的协议
    class Tout : showTicketNumberProtocol  {
        //终于,下面这个函数可以不实现,并且不会报错了
        @objc func showTicketNumber() {  //由于showTicketNumberProtocol含有OC特性,于是这个协议中所有的函数在实现之前都要有@objc来修饰
            print("123456")
        }
    }
    

    Swift中的协议与代理设计模式

    首先要明确,在Swift中一个协议不仅可以被类遵守,还可以被结构体/枚举来遵守,所以当我们在Swift中使用代理设计模式时,要明确的告诉编译器,我定义的这个协议是供一个class来遵守的,反例如下:

    反例:书接上文的例子,托人买火车票
    class Person {
        weak var delegate : buyTicketProtocol?  //此时会处于编译报错的状态,这是因为buyTicketProtocol这个协议并没有明确规定是由类来遵守的
    }
    

    正确的做法如下:

    例:托人买火车票(协议的知识点的小综合^ ^)
    //父协议
    @objc  //含有OC特性的代码
    protocol showTicketNumberProtocol : class {  //遵守class,表示这个协议由class来遵守
        optional func showTicketNumber() -> Void  //展示票号(可选实现)
    }
    //子协议
    protocol buyTicketProtocol : showTicketNumberProtocol  //遵守showTicketNumberProtocol,表示能实现当前协议中的函数的人,必须要能实现showTicketNumberProtocol中定义的必须实现的函数
    showTicketNumberProtocol  {  //买票
        func buyTicket() -> Void
    }
    //黄牛类
    class Tout : buyTicketProtocol  {  //黄牛类,遵守协议,代表能买到票
        func buyTicket() {  //实现买票函数
            print("here's your ticket")
        }
    //    @objc func showTicketNumber() {  //此处并没有实现展示票号的函数,不会报错
    //        print("123456")
    //    }
    }
    //需要买票的Person类
    class Person {  //定义Person类
        weak var delegate : buyTicketProtocol?  //定义一个代理,代理必须能买到票
    }
    //外部调用
            //实例化对象
            let p = Person()  //创建一个需要买火车票的人
            let t = Tout()  //创建一个会买火车票的黄牛
            //调用代理方法
            p.delegate = t  //人的代理设置为黄牛
            p.delegate?.buyTicket()  //黄牛买了一张火车票,控制台打印:here's your ticket
            // p.delegate?.showTicketNumber!()  //这个函数没有被实现,所以此处使用!会导致程序崩溃
            p.delegate?.showTicketNumber?()  //如果使用可选链,那么这个方法将不会执行,也不会报错
            p.delegate = nil  //此处会自动调用Tout的deinit方法,表示:如果人不找黄牛买火车票,黄牛就会饿死,诶?我为什么要写这一句...无视,无视
    

    相关文章

      网友评论

        本文标题:Swift超基础语法(协议与代理篇)

        本文链接:https://www.haomeiwen.com/subject/snfqsttx.html