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

代理设计模式是开发中比较常见的设计模式之一,那么在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超基础语法(协议与代理篇))