Swift中的open关键字:它是什么以及为什么初学者需要了解它

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Swift中的open关键字隐藏了什么?初学者解析



你是否曾在Swift中编写过一个类,给它添加了public,然后试图在另一个模块中继承它——却遇到了编译错误?如果是这样,你并不孤单。这个问题是Stack Overflow上Swift初学者开发者中最常见的问题之一。成千上万的人都在同一个问题上栽了跟头:open关键字。



在本文中,我们将一劳永逸地弄清楚Swift中的open是什么,它与public有何不同,何时应该使用它,以及何时绝对不能使用它。我们将编写实际代码,查看错误并学习如何修复它们。开始吧!



Swift中的访问修饰符系统:简要入门



在深入探讨open之前,让我们回顾一下Swift中有哪些访问级别。共有五个(从最封闭到最开放):



  • private — 仅在同一文件和同一声明内可访问(例如,在类内部)。
  • fileprivate — 在整个文件范围内可访问。
  • internal — 在整个模块内可访问(这是默认级别)。
  • public — 可从其他模块访问,但不能继承和重写。
  • open — 可从其他模块访问,可以继承和重写。


主要的悬念在于public和open之间的区别。乍一看它们很相似:两者都允许从另一个模块访问类、方法或属性。但有一个根本性的区别,我们现在将通过示例来解析。



示例:一个无法扩展的public类



假设你正在编写一个用于网络操作的库(框架)。你创建了一个NetworkService类并将其设为public:



// 模块:MyNetworkingFrameworkpublic class NetworkService {    public func fetchData() {        print("从网络获取数据...")    }}


现在,另一位开发者连接了你的框架,并希望基于它创建自己改进的类:



// 模块:MyAppimport MyNetworkingFramework

// 错误!无法从public类继承class MyNetworkService: NetworkService { override func fetchData() { print("我的自定义获取...") }}


编译器将报错。为什么?因为public是从另一个模块只读的访问权限。你可以使用类的实例,调用它的方法,但不能继承它。这是有意为之:库的作者希望控制哪些类可以扩展,哪些不可以。



解决方案:使用open



如果库的作者希望允许继承,他必须明确指定open:



// 模块:MyNetworkingFrameworkopen class NetworkService {    open func fetchData() {        print("从网络获取数据...")    }}


现在,在另一个模块中可以安全地继承和重写方法:



// 模块:MyAppimport MyNetworkingFramework

class MyNetworkService: NetworkService { override func fetchData() { print("我的自定义获取,带有额外日志记录...") super.fetchData() }}


这就是全部魔法。open关键字是在模块外部进行继承和重写的许可。



为什么open对架构很重要?



Swift和Apple的开发者引入这种区别并非无缘无故。它有助于设计稳定且安全的API。想象一下,你发布了一个库,其中所有的类都是open。

博客

书籍推荐