Swift-访问控制(Access Control)

96
xuq
2015.09.19 16:38 字数 804

Swift中包含三种权限控制

  • public (公开, 供外部调用)
  • internal (默认, 限module内使用)
  • private (私有, 限source file内使用)

名词解释

  1. module是个代码发布单元(如Framework或者应用程序), 通过使用import关键字导入使用
  2. A source files是module中的一个swift文件 (实际情况就是一个app或者framework中的一个swift文件)

internal

默认控制权限, 如果单target用户,不需要刻意强调控制权限,默认权限就足够了

public

使用场景framework, 用于公开api调用, 其他framework内部使用方法采用 internal 方便framework内部调用,但是对framework外部不可使用

private

原文为(use in sourcefile), 即定义的private仅能在当前文件使用,子类及继承均不能使用

使用等级

private < internal < public

测试访问控制

@testable 使得internal的也可以被访问

使用规则

不能包含比自己使用等级更大的实体

Demo

新建一个workspace, 包括一个framework(CECModuleFrame)和一个demo(ModuleDemo)
在framework中新建类 ModuleApi.swift

import Foundation

class ModuleApi {
    public func helloWorld() { //警告:Declaring a public instance method for an internal class,表明不能在一个internal权限的类中新建一个public的方法
        print("Hello world")
    }
}

如上代码所示, 如果不写控制权限关键词,则默认为internal, 为了让文件被外部访问,需要添加public关键词,如下所示
public class ModuleApi {
    public init() {

    }

    // 想被外部访问,则必须添加public关键词
    public let somePublicProperty = "Module"

    // 想被外部访问,则必须添加public关键词
    public func helloWorld() { 
        print("Hello world")
    }
}

// 外部使用方法:
let api = ModuleApi()
api.helloWorld()  // 输出: Hello world
print(api.somePublicProperty) // 输出Module

TupleType访问权限

多个对象,返回最小权限类型

(public, internal) 得到的是internal权限
(public, private) 得到的是private权限

方法访问控制

public class ModuleApi {
    public init() {

    }

    // 提示出错:Method must be declared private because its result uses a private type
    func someFunction()->(PrivateClass, InternalClass) {

    }
}

private class PrivateClass {
}

internal class InternalClass {
}

Enum类型

选项的权限跟着enum的定义

public enum CompassPoint {
      case North // 访问权限为public
}

类\常量\变量\属性等都遵循着使用规则

Getter & Setter

在var 或者subscript前使用private(set) or internal(set)获得更低的使用权限

struct TrackedString {
    private(set) var numberOfEdits = 0
    var value: String = "" {
        didSet {
            numberOfEdits++
        }
    }
}

// 可以联合使用public和private(set)
public struct TrackedString {
    public private(set) var numberOfEdits = 0
    public var value: String = "" {
        didSet {
            numberOfEdits++
        }
    }
    public init() {}
}

Initializers

  1. A required initializer must have the same access level as the class it belongs to.”
  2. As with function and method parameters, the types of an initializer’s parameters cannot be more private than the initializer’s own access level.

Default Initializers

As described in Default Initializers, Swift automatically provides a default initializer without any arguments for any structure or base class that provides default values for all of its properties and does not provide at least one initializer itself.

A default initializer has the same access level as the type it initializes, unless that type is defined as public. For a type that is defined as public, the default initializer is considered internal. If you want a public type to be initializable with a no-argument initializer when used in another module, you must explicitly provide a public no-argument initializer yourself as part of the type’s definition.

类或者Struct如果使用了public,默认初始器是internal的,所以需要提供一个对应的public的初始器

Swift