iOS 中属性与方法的访问权限等级

在 Xcode 中共有五种对变量和方法的访问权限, 其等级从低到高依次是:

  1. private
  2. fileprivate
  3. internal
  4. public
  5. open

五种等级 (由低到高)

private

只在本文件且本类 (或本类扩展) 中可以被访问

  • 如果在一个文件中且任何类外声明一个 private 属性, 那么该属性可被该文件所有位置访问到, 但是外部文件不能访问到此属性
  • 如果将类中某个属性 abc 设为 private, 在其他文件中对该类进行 extension, 那么在该 extension 中是不能被访问到 abc 的

fileprivate

只在本文件中可以被访问

如果一个文件中有两个及以上的类的话, 那么被 fileprivate 标记的类中的属性就可以在本文件的多个类中被访问, 而被 private 访问的就只能在本文件的本类 extension 中被访问

对于 top level 的 类 / 方法 / 变量来说, 使用 fileprivate 或 private 没有区别

internal

本模块内可以使用

xcode 默认使用本种权限, cocoapods 即一个单独的模块 module

public

本项目中各 module 任意读取, 不能在其他 module 中继承重写. 框架, api, 库中经常用, 个人开发少用

open

本项目中各 module 任意读取, 重写, 继承

对 getter 与 setter 设置不同的访问级别

swift
// 把 getter 设为 public 级别, setter 设为 private 级别
public private(set) var disposeBag = DisposeBag()
// 把 getter 设为默认的 internal 级别, setter 设为 private 级别
private(set) var name: String?

迪米特法则与实践

迪米特法则(LoD, Law of Demeter), 如果一个类知道了太多不属于它本身的内容, 则代表这个类与外部的耦合程度越高, 越不灵活, 越难以复用. 但是如果这个类完全不知道外部信息, 那么物件之间也无法合作, 整个应用也就无法运行. 因此我们要保证每个类对外界开放最少的属性, 拥有对外界最少的知识, 这样既可以确保物件之间的合作, 也较灵活, 便于复用与解耦

law 的意思是法则, 比原则 principle 要强势的多. 在 principle 的世界中, 如果两个 principle 之间有所抵触, 那么我们会衡量彼此的价值, 然后取其中地位较高的, 也就是说 principle 之间是可以相互妥协的, 但是 law 就不是这样的, 他代表一种绝对的法则, 没有什么可以撼动 Lod 的地位.

iOS 开发中, 因为 Swift 语言对于声明的属性是 internal 级别的, 这样并不能保证每个类的最少暴露. 我的建议是养成在定义方法或者属性的时候手动添加 private 或 fileprivate 的习惯, 这样长此以往我们可以将这些经典的设计模式融入到我们的骨髓中.

我一直在想为什么 Swift 不将默认的级别设为 private, 而是设为模块内均可以访问的 internal, 现在我的看法是 Swift 为了让基础差的人容易上手, 更容易接受.

本博客文章采用 CC 4.0 协议,转载需注明出处和作者。

鼓励作者