美文网首页Swift
Swift - Access Control

Swift - Access Control

作者: ienos | 来源:发表于2019-04-11 18:05 被阅读0次

访问控制模型是基于 Modules & Source Files
作用:隐藏代码的实现,指定接口能够被访问和使用

Module

  • 是单一的代码分配单元 - 一个框架或应用程序会作为独立的单元构建和发布并且可以使用 Swift 的 import 关键字导入到另一个 module
  • Swift 的 module 相当于每一个 Target (app bundle OR framework)

Source File

  • 在一个 module 中的一个 Swift 源代码文件
  • 通常每一个类型分配在单独源文件,一个源文件也可以包括定义多个类型、方法等等

五种访问等级

从高到低:open / public / internal / fileprivate / private

Open & Public

  • 在被定义的 module 中使用
  • 在其他 module 中使用,imports 被定义的 module
  • 指定 Framework 公共接口,使用 open 和 public 修饰

Internal

  • 在被定义的 module 中使用
  • 在 app 或 Framework 内部结构时使用

File-private

  • 在被定义的源文件中使用

Private

  • 定义的范围内 + 同文件内的 extension 中使用

Open 只能用于类和类成员,以下几点不同于 Public

  • < Public(类),只能在所在的 module 被子类化
  • < Public(类成员),只能在所在的 module 被子类重写
  • Open(类)能够在所在的 module 中被子类化,或者在任何已 import module 的 module 中被子类化
  • Open(类成员)能够在所在的 module 中被子类化,或者在任何已 import module 的 module 中被子类重写

✨访问权限的原则

实体不能被另外一个低访问权限的实体定义
eg:

  • 一个 public 变量不能被定义有一个 internal / file-private / private 类型定义,因为类型也许不能在 public 变量使用时有效
  • 方法 level !> 参数 level & return level

默认访问等级 - internal

Unit Test Targets

除了标记 Open 和 Public,能够访问任何 internal 实体的方式:在 import module 前加 @testable

Frameworks

open / public 修饰 API

自定义类型

  • 如果定义类型为 private / file-private,默认成员的访问等级也是 private / file-private
  • 如果定义类型为 internal / public,默认成员的访问等级是 Internal(如果需要,用 public 修饰,提供选择性发布,避免将内部类型作为 API)
fileprivate class SomeFilePrivateClass {
    func someFilePrivateMethod() {}
    private func somePrivateMethod() {} 
}

元祖类型

整个元祖类型的访问权限,决定于元祖中所有类型的最低访问权限,不能特指访问权限

方法类型

方法类型的访问权限,决定于方法参数类型和返回值类型的最低访问权限

func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // function implementation goes here
}
// 也许会期望方法的默认访问权限为 internal,但是实际上取决于元祖类型 
// 并且在这里不能用 public 和 internal 修饰改方法

枚举类型

  • 不能为独立的枚举 case 指定不同的访问权限
  • 独立的枚举 case 自动为枚举类型的相同访问权限
  • 原生值 和 关联值 必须至少和枚举有相同的访问等级

嵌套类型

  • 嵌套类型在一个 private 有一个自动 private 访问类型
  • 嵌套类型在一个 file-private 类型中自动有 file-private 访问类型
  • 嵌套类型在在一个 public OR internal 类型中自动有 internal 中
  • 如果需要 public 类型就显式指定

子类化

  • 一个子类不能有高于父类的访问权限
  • 重写可以让继承的类成员比其父类更容易访问
public class A {
    fileprivate func someMethod() {}
}

internal class B: A {
    override internal func someMethod(){
      super.someMethod()
  }
}

常量、变量、属性和下标

  • 不能比它的类型还高级
  • 下标不能比它的索引类型和返回值更高级
private var privateInstance = SomePrivateClass()

Setter and Getter

  • setter / getter 自动接收 常量、变量、属性、下标的访问等级
  • fileprivate(set) / private(set) / internal(set) 修饰变量 OR 下标,这个规则应用于存储属性和计算属性
struct TrackedString {
// setter: private ; getter: internal
    private(set) var numberOfEdits = 0
    var value: String = "" {
          didSet {
              numberOfEdit += 1
          }
    }
}
public struct TrackedString {
    // 默认是 getter internal;此时设置为 getter public
    public private(set) var numberOfEdits = 0
    public var value: String = "" {
          didSet {
                numberOfEdits += 1
          }
    }
    public init() {}
}

初始化

  • 自定义初始化器能够被定义低于或等于他们的类型
  • 除了 Required 初始化器必须和类有相同的访问等级
  • 初始化器的参数不能低于初始化器的本身访问等级

默认初始化器

  • Swift 自动提供一个没有任何参数的默认初始化,为结构体和类的所有属性提供默认值,但没有提供初始化本身的方法
  • 默认的初始化器有和类型相同的访问等级,除了public 的类型

结构体类型的默认 Memberwise 初始化器

  • 如果结构体的所有存储属性是 private, 结构体类型也是 private
  • 如果结构体的所有存储属性时 file-private,结构体类型也是 file-private
  • 如果需要 public 结构体类型能够在另外的 module 中使用,必须提供一个 public memberwise 初始化器

协议

-requirement 自动设置与协议相同的访问等级,并且不能设置与其不同的等级,以确保所有 requirement 能够有效适用任何遵循该协议的类型

协议继承

最高访问权限为父协议的等级

协议遵循

  • 一个类型能够遵循一个低于它访问等级的协议
  • 一个类型遵循一个协议,访问等级为协议和类型的最低访问等级
  • 一个类型遵循一个协议必须确保每一个 requirement 至少有和协议相同的访问等级

遵循协议是全局的:一个类型不能以两种不同的方式遵循一个协议

Extensions

class / structure / enumeration

  • 新扩展的类成员和被扩展类型的访问等级一致
    extension public / internal -> type member internal
    extension private -> type member private
    extension file-private -> type member file-private

  • 可以为所有在 extension 的成员定义一个新的等级,同样也可以针对单个成员重写
    eg: private extension

  • 如果使用了 extension 添加协议遵循,不能提供一个显式的访问等级修饰一个扩展

在 Extension 中的私有成员

  • 声明一个私有成员在初始声明中,能在同个文件的 extension 中访问
  • 在 extension 中声明私有成员,其他来自同一文件的其他 extension 中访问
  • 在 extension 中声明私有成员,能够被来自同个文件的初始声明中访问

泛型

泛型类型 / 泛型方法 level = minimum (泛型类型 / 泛型方法,类型参数上的类型约束)

类型别名

类型别名 level <= 类型 level

相关文章

网友评论

    本文标题:Swift - Access Control

    本文链接:https://www.haomeiwen.com/subject/colzmqtx.html