0%

访问控制

访问控制

Access control restricts access to parts of your code from code in other source files and modules.

You can assign specific access levels to individual types (classes, structures, and enumerations), as well as to properties, methods, initializers, and subscripts belonging to those types. Protocols can be restricted to a certain context, as can global constants, variables, and functions.

The various aspects of your code that can have access control applied to them (properties, types, functions, and so on) are referred to as “entities” in the sections below, for brevity.

Modules and Source Files(模块和源文件)

Swift’s access control model is based on the concept of modules and source files.

模块
A module is a single unit of code distribution—a framework or application that is built and shipped as a single
unit and that can be imported by another module with Swift’s import keyword.
(一个模块就是一个独立的代码分发单元,比如一个framework.xq注:比如你提供给别人使用的一个第三方库就是一个单独的模块)
具体一点:
Each build target (such as an app bundle or framework) in Xcode is treated as a separate module in Swift. If you group together aspects of your app’s code as a stand-alone framework—perhaps to encapsulate and reuse that code across multiple applications—then everything you define within that framework will be part of a separate module when it is imported and used within an app, or when it is used within another framework.

源文件
A source file is a single Swift source code file within a module (in effect, a single file within an app or framework). Although it is common to define individual types in separate source files, a single source file can contain definitions for multiple types, functions, and so on.
(一个源文件就是模块里一个单独的Swift源代码文件,通常不同的源文件定义的类型也是不同的,但是一个单独的源文件可以定义多种类型,函数等.xq注:你可以在一个源文件里定义多个类)

Access Levels(访问级别)

Swift provides five different access levels for entities within your code. These access levels are relative to the source file in which an entity is defined, and also relative to the module that source file belongs to.
(Swfit提供5种不同的访问级别.这些访问级别对定义实体的源文件产生影响,也对包含这些源文件的模块产生影响.)

  • Open access and public access enable entities to be used within any source file from their defining module, and also in a source file from another module that imports the defining module. You typically use open or public access when specifying the public interface to a framework. The difference between open and public access is described below. (open和public修饰词表示允许模块内的任意源文件访问这些实体.如果其他模块的源文件导入了定义它们的模块,那么其他模块的源文件也可以访问这些实体.通常给framework指定公共接口时用到open或public)
  • Internal access enables entities to be used within any source file from their defining module, but not in any source file outside of that module. You typically use internal access when defining an app’s or a framework’s internal structure. (Internal修饰词表示只能是定义它们的模块里的任意源文件可以访问.模块外的任何源文件都访问不到.通常在定义一个app或framework的内部结构时使用internal)
  • File-private access restricts the use of an entity to its own defining source file. Use file-private access to hide the implementation details of a specific piece of functionality when those details are used within an entire file. (fileprivate用于将实体的使用限制在定义它的源文件里,使用fileprivate可以用来隐藏指定功能块的实现细节,这些实现细节是在整个文件内使用的)
  • Private access restricts the use of an entity to the enclosing declaration. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration. (private用于将实体的使用限制在定义它的花括号内.使用private可以用来隐藏指定功能块的实现细节,这些实现细节仅在单独的某个声明里使用)

Open access is the highest (least restrictive) access level and private access is the lowest (most restrictive) access level.

open和public的区别

Open access applies only to classes and class members, and it differs from public access as follows:

  • Classes with public access, or any more restrictive access level, can be subclassed only within the module where they’re defined.(public修饰的类仅能在模块内被子类化)
  • Class members with public access, or any more restrictive access level, can be overridden by subclasses only within the module where they’re defined.(public修饰的类成员仅能在模块内被子类重写)
  • Open classes can be subclassed within the module where they’re defined, and within any module that imports the module where they’re defined.(open修饰的类可以在任意模块被子类化)
  • Open class members can be overridden by subclasses within the module where they’re defined, and within any module that imports the module where they’re defined.(open修饰的类成员可以在任意模块被重写)

Guiding Principle of Access Levels(访问级别的指导准则)

Access levels in Swift follow an overall guiding principle: No entity can be defined in terms of another entity that has a lower (more restrictive) access level.
(xq注:Swift不允许高级别的实体定义在低级别的实体内,基本上你只能缩小访问级别而不能扩大)

举例:

  • A public variable cannot be defined as having an internal, file-private, or private type, because the type might not be available everywhere that the public variable is used.

  • A function cannot have a higher access level than its parameter types and return type, because the function could be used in situations where its constituent types are not available to the surrounding code.

Default Access Levels(默认的访问级别)

All entities in your code (with a few specific exceptions, as described later in this chapter) have a default access level of internal if you do not specify an explicit access level yourself. As a result, in many cases you do not need to specify an explicit access level in your code.

Access Levels for Frameworks

When you develop a framework, mark the public-facing interface to that framework as open or public so that it can be viewed and accessed by other modules, such as an app that imports the framework. This public-facing interface is the application programming interface (or API) for the framework.

Access Control Syntax

Define the access level for an entity by placing one of the open, public, internal, fileprivate, or private modifiers before the entity’s introducer.

Unless otherwise specified, the default access level is internal.

Custom Types(自定义类型访问级别)

If you want to specify an explicit access level for a custom type, do so at the point that you define the type. The new type can then be used wherever its access level permits.

The access control level of a type also affects the default access level of that type’s members (its properties, methods, initializers, and subscripts). If you define a type’s access level as private or file private, the default access level of its members will also be private or file private. If you define a type’s access level as internal or public (or use the default access level of internal without specifying an access level explicitly), the default access level of the type’s members will be internal.

注意:A public type defaults to having internal members, not public members. If you want a type member to be public, you must explicitly mark it as such.

1
2
fileprivate class SomeFilePrivateClass {  // explicitly file-private class
func someFilePrivateMethod() {} // implicitly file-private class member private func somePrivateMethod() {} // explicitly private class member }

Function Types

The access level for a function type is calculated as the most restrictive access level of the function’s parameter types and return type. You must specify the access level explicitly as part of the function’s definition if the function’s calculated access level does not match the contextual default.

Subclassing

You can subclass any class that can be accessed in the current access context. A subclass cannot have a higher access level than its superclass.

In addition, you can override any class member (method, property, initializer, or subscript) that is visible in a certain access context(xq注:要能重写,才有后面的重写之后能够xxx).An override can make an inherited class member more accessible than its superclass version.

Constants, Variables, Properties, and Subscripts

A constant, variable, or property cannot be more public than its type. It is not valid to write a public property with a private type.

If a constant, variable, property, or subscript makes use of a private type, the constant, variable, property, or subscript must also be marked as private.

Getters and Setters

Getters and setters for constants, variables, properties, and subscripts automatically receive the same access level as the constant, variable, property, or subscript they belong to.

You can give a setter a lower access level than its corresponding getter, to restrict the read-write scope of that variable, property, or subscript. You assign a lower access level by writing fileprivate(set), private(set), or internal(set) before the var or subscript introducer.

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

上述代码的解释:The TrackedString structure and the value property do not provide an explicit access-level modifier, and so they both receive the default access level of internal. However, the access level for the numberOfEdits property is marked with a private(set) modifier to indicate that the property’s getter still has the default access level of internal, but the property is settable only from within code that’s part of the TrackedString.

Protocols

If you want to assign an explicit access level to a protocol type, do so at the point that you define the protocol. This enables you to create protocols that can only be adopted within a certain access context.

The access level of each requirement within a protocol definition is automatically set to the same access level as the protocol. You cannot set a protocol requirement to a different access level than the protocol it supports. This ensures that all of the protocol’s requirements will be visible on any type that adopts the protocol.

Protocol Inheritance

If you define a new protocol that inherits from an existing protocol, the new protocol can have at most the same access level as the protocol it inherits from. You cannot write a public protocol that inherits from an internal protocol, for example.

Protocol Conformance(协议遵守)

A type can conform to a protocol with a lower access level than the type itself.

When you write or extend a type to conform to a protocol, you must ensure that the type’s implementation of each protocol requirement has at least the same access level as the type’s conformance to that protocol. For example, if a public type conforms to an internal protocol, the type’s implementation of each protocol requirement must be at least “internal”.

Extensions

You can extend a class, structure, or enumeration in any access context in which the class, structure, or enumeration is available. Any type members added in an extension have the same default access level as type members declared in the original type being extended. If you extend a public or internal type, any new type members you add have a default access level of internal. If you extend a file-private type, any new type members you add have a default access level of file private. If you extend a private type, any new type members you add have a default access level of private.(当类,结构体,枚举在访问上下文中可用时,那么你就可以扩展一个类,结构体,枚举)

Alternatively, you can mark an extension with an explicit access-level modifier (for example, private extension) to set a new default access level for all members defined within the extension.

Adding Protocol Conformance with an Extension

You cannot provide an explicit access-level modifier for an extension if you are using that extension to add protocol conformance. Instead, the protocol’s own access level is used to provide the default access level for each protocol requirement implementation within the extension.

觉得文章有帮助可以打赏一下哦!