如何为特定类声明协议

236 阅读2分钟

在日常的 swift 开发中,经常会用到协议,协议定义了适合特定任务或功能的方法、属性和其他需求的蓝图。然后,协议可以被类、结构或枚举所采用,以提供这些需求的实际实现。任何满足协议要求的类型都被称为符合该协议。

但有时你可能希望限制特定类才能使用的协议。今天我们就聊聊这个主题。

声明语法

如果想让某个协议只被某个类遵守,比如声明一个协议只能被 UIViewController 遵守,有两种声明方式:

// 方式一
protocol MyViewControllerProtocol: UIViewController { /*...*/ }

// 方式二
protocol MyViewControllerProtocol where Self: UIViewController { /*...*/ }

此时 MyViewControllerProtocol 协议将其符合类型限制为 UIViewController 的子类(或类型)。

报错

如果你尝试从非 UIViewController 子类使用此协议

class MyClass { }

extension MyClass: MyViewControllerProtocol {
    
}

将收到编译器错误:

MyViewControllerProtocol' requires that 'MyClass' inherit from 'UIViewController'

Type 'MyClass' does not conform to protocol 'MyViewControllerProtocol'

这个特性的好处是什么?

这样做的好处主要有两点

1、你的协议真的是为 UIViewController 设计的,其他的类即使能够遵守,也无法使用。

2、在这个 MyViewControllerProtocol 协议里可以直接访问 UIViewController 的属性和方法。

protocol MyViewControllerProtocolUIViewController {
    func changeTitle(_ newTitleString)
}

extension MyViewControllerProtocol {
    func changeTitle(_ newTitleString) {
        // 可以直接访问 UIViewController 的属性和方法
        self.title = newTitle
    }
}

与扩展一起使用

对于一个协议,你还可以将此语法与协议扩展一起使用。比如为某个协议的指定的类添加默认实现。

protocol MyProtocol {
    func changeTitle(_ newTitleString)
}

extension MyProtocol where SelfUIViewController {
    func changeTitle(_ newTitleString) {
        self.title = newTitle
    }
}

在上边的示例中,默认实现了 UIViewControllerchangeTitle 方法,因此任何 UIViewController 只要遵守了 MyProtocol 协议,就会自动拥有 changeTitle 这个方法:

class ViewControllerUIViewControllerMyProtocol {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 因为遵守了 MyProtocol 协议,所以可以直接调用 changeTitle 方法
        changeTitle("new title")
    }
}

点击下方公众号卡片,关注我,每天分享一个关于 iOS 的新知识

本文同步自微信公众号 “iOS新知”,每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!