编程iOS开发者

解释一下Swift中private/protected/internal/public/open访问修饰符的工作原理。每个修饰符什么时候最好使用,并且在实际项目中可能会遇到哪些错误?

用 Hintsage AI 助手通过面试

答案

在Swift中,有五种访问级别可用于类型成员(属性、方法等)以及类型本身:

  • open — 公开性最高。可以在模块外继承和重写。
  • public — 在模块外可用,但不能被重写/继承。
  • internal(默认) — 在模块内部可用。
  • fileprivate — 仅在文件范围内可用。
  • private — 仅在声明区域内可用(扩展也在该范围内)。

使用规则:

  • 对于不应在声明外可见的逻辑,请使用private
  • fileprivate — 如果需要在一个文件中交换数据(例如,在两个相关的扩展之间)。
  • internal — 模块中所有公共接口的默认值。
  • public/open — 用于其他模块/框架使用的API。

示例:

open class MyOpenClass {} public class MyPublicClass {} internal class InternalClass {} fileprivate class FilePrivateClass {} private class PrivateClass {}

具有陷阱的问题

open和public在描述类时有什么不同?为什么并非所有public类都可以继承?

答案: open标记类/方法为可在模块外进行重写和继承。public仅开启使用权限,但不允许在模块外创建子类。从某种意义上说,这保护了实现不受不必要的更改,而另一方面,仅开放所需的扩展点。

public class PublicClass {} open class OpenClass {} // 在另一个模块中: class InheritFromOpen: OpenClass {} // OK class InheritFromPublic: PublicClass {} // 错误!

由于对主题细节的不熟悉而导致的实际错误示例


故事

在公共库中,一个类被标记为public,外部项目试图重写其方法进行扩展。由于对public和open之间差异的错误理解,项目未能编译——这导致团队多花了一周的时间来修正接口。


故事

在一个文件内部,尝试通过扩展访问private属性——但属性被声明为private而不是fileprivate。这导致了编译错误,只有在集成构建时才被注意到。


故事

在一个具有多个框架的应用中,所有类型均被标记为internal(默认)。当需要在模块间使用类型时,接口不可用——不得不将数十个声明重写为public,花费了额外的时间和测试。