Swift中的'open'关键字是什么?

393

标准库中的ObjectiveC.swift文件在大约第228行附近包含以下几行代码:

extension NSObject : Equatable, Hashable {
  /// ...
  open var hashValue: Int {
    return hash
  }
}

在这个上下文中,open var是什么意思,或者说open关键字一般指什么?


2
可能相关:https://dev59.com/NWAg5IYBdhLWcg3wE3nQ#39697920(“`open`和`public`之间有什么区别?”) - Ahmad F
1
旁注:关键字“open”来自于“开放扩展,关闭修改”的概念。 - Sazzad Hissain Khan
5个回答

675

open是Swift 3中的一种新访问级别,随着实现SE-0117 允许区分公共访问和公共可重载性而引入。

它可在2016年8月7日的Swift 3快照和Xcode 8 beta 6中使用。

  • open类可以在定义模块之外被访问和子类化。 open类成员可以在定义模块之外被访问和重载。
  • public类可以在定义模块之外被访问但不能被子类化。 public类成员可以在定义模块之外被访问但不能被重载。

因此,open是先前Swift版本中的public,而public的访问范围已受限制。或者像Chris Lattner在SE-0177: Allow distinguishing between public access and public overridability中所说:

“open”现在比“public”更加“公开”,提供了一个非常简单和清晰的模型。

在您的示例中,open var hashValue是一个属性,在NSObject子类中可以被访问和重写。

更多示例和详细信息,请参阅SE-0117


22
在Swift 3中,public就像Swift 2中的public final,而open则相当于public - Clashsoft
16
在Swift 3中,“open”相当于Swift 2中的“public”,而Swift 3中的“public”在Swift 2中没有对应的概念。(一个final类无法被任何模块中的子类化。) - Martin R
69
这真是令人捧腹的违反直觉。感谢提供摘要。 - GoldenJoe
7
同意 @MikeS 的看法,而且缺乏向后兼容性使得这变成了一个糟糕的混乱。 - HughHughTeotl
20
苹果公司的标语是“Think Different”,即使这并不必要也要做到不同。 - Varun Nath
显示剩余11条评论

28

理解 open 为

在其他模块中开放继承

我再次强调,open 表示在包含定义模块的其他模块中,可以对开放类进行子类化。对于开放变量和函数,其他模块可以重写它们。这是最不限制的访问级别。它与公共访问一样好,唯一的区别是公共访问在其他模块中关闭继承。

来自 Apple Docs:

开放访问仅适用于类和类成员,并且与公共访问有以下不同之处:

  1. 使用 public 访问或任何更严格的访问级别定义的类,只能在定义它们的模块内进行子类化。

  2. 使用 public 访问或任何更严格的访问级别定义的类成员,只能在定义它们的模块内被子类覆盖。

  3. 开放类可以在定义它们的模块内进行子类化,也可以在导入定义它们的模块的任何模块内进行子类化。

  4. 开放类成员可以被定义它们的模块内的子类覆盖,也可以在导入定义它们的模块的任何模块内被子类覆盖。


公开应该意味着对所有人开放,但在Swift中却只意味着内部开放。开放的含义就是公开应该具有的含义。听起来像是他们匆忙添加了这个功能,没有经过深思熟虑。 - ATL_DEV

12

Open是一种访问级别,旨在对Swift中的类继承施加限制。

这意味着open访问级别只能应用于类和类成员

在类中

在定义它的模块和导入该类所在模块的模块中,可以对开放类进行子类化。

在类成员中

类成员也是如此。在定义方法的模块和导入包含该方法的模块中,可以通过子类来覆盖开放方法。

更新的原因

某些库和框架的类不适合进行子类化,这样做可能会导致意外行为。Native Apple库也不允许覆盖相同的方法和类,因此添加了这个新特性,将根据需要应用公共和私有访问级别。

有关更多详细信息,请参见Apple Access Control文档


2

在处理多个模块时,需要使用open关键字。

open类可以在定义模块之外被访问和继承。open类成员可以在定义模块之外被访问和重写。


1

open仅供另一个模块使用,例如:CocoaPods或单元测试,我们可以继承或覆盖。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接