美文网首页iOS Developer
swift入门23 访问控制

swift入门23 访问控制

作者: C93zzo | 来源:发表于2017-04-26 16:29 被阅读40次

    模块与源文件

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

    swift的访问控制模型是基于模型和源文件的。

    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.

    一个模块是一个代码分配单位—一个框架或应用就是一个单位,可以被其他模块用import关键字引入。

    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.

    在swift中,每个Xcode的构建目标(比如一个app bundle或框架)都被视为一个独立的模块。如果你把你的app的代码打包为一个独立的框架---或许用于封装和重用—那么你在那个框架内定义的所有东西都会成为一个独立模块的一部分。

    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源代码文件(实际上,就是一个app或一个框架内的一个文件)。虽然,通常都是在不同的源文件中定义独立的类型,但一个源文件可以包含多个类型,多个函数的定义。(有点绕啊,我翻译得都有点绕。。。。。)

    访问级别(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.

    swift提供了五种不同的访问级别。

    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.

    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.

    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.

    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.

    open和public使得实体可以在定义它们的模块内的任何源文件中使用,也可以在引入此定义模块的其他模块的源文件中使用。open和public多数用于在一个框架中指定公共的(public)接口。open和public的区别下面介绍。

    Internal使得实体可以在定义它们的模块内的任意源文件中使用,但不能被该模块外的源文件使用。internal多数用于为app或框架定义一个内部的(internal)结构。

    File-private限制实体只能在它的定义源文件中使用。当某些功能只在实体文件内使用时,可以用file-private来隐藏这些特定功能的实现细节。

    Private限制实体只能在声明内使用。当某些功能只在它的声明内使用时,可用private来隐藏实现细节。

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

    open的访问权限最高(最少限制),private的访问权限最低(限制最多)。

    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.

    Class members with public access, or any more restrictive access level, can be overridden by subclasses only within the module where they’re defined.

    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 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只适用于类和类成员,它和public的区别如下:

    public修饰的类,或者其他更严格的访问权限修饰的类,只能在它们被定义的模块中被继承。

    public修饰的类成员,或者其他更严格的访问权限修饰的类成员,只能在它们被定义的模块内的子类中重写。

    open修饰的类可以在它们被定义的模块中被继承,也能在引入了此定义模块的其他模块中被继承。

    open修饰的类成员可以在它们被定义的模块的子类中被重写,也能在引入了此定义模块的其他模块内被重写。

    Marking a class as open explicitly indicates that you’ve considered the impact of code from other modules using that class as a superclass, and that you’ve designed your class’s code accordingly.

    把一个类标记为open的,就显式地表明你已经考虑了其他模块的代码的影响,而且你已经相应地设计了你的类的代码。

    访问级别的指导原则

    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.

    swift中的访问级别遵循一个总的原则:一个实体不能定义在一个访问权限更低的实体里。

    For example:

    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.

    比如:

    一个public的变量不能定义在interal,file-private,或private的类型里,因为这个类型或许在public变量使用的地方无法获取。

    一个函数不能拥有比它的参数类型和返回类型更高的访问权限,因为这个函数可能会用在那些无法获取它的组成类型的地方。

    默认访问级别

    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.

    你代码中的所有实体(只有少数例外,稍后会讲到)有一个默认的访问权限:internal,如果你不显式的指定访问级别的话。因此,在很多时候,你不需要显式的指定访问级别。

    单一目标app的访问级别(Access Levels for Single-Target Apps)

    When you write a simple single-target app, the code in your app is typically self-contained within the app and does not need to be made available outside of the app’s module. The default access level of internal already matches this requirement. Therefore, you do not need to specify a custom access level. You may, however, want to mark some parts of your code as file private or private in order to hide their implementation details from other code within the app’s module.

    当你写一个简单的单一目标的app时,你的app里的代码都是自包含的,不需要被此app外部模块访问。默认的interal访问权限已经满足这个要求了。因此,你不需要指定一个访问级别。然而,你或许想把你代码中的某些部分标记为file private 或private的,为了隐藏某些实现细节。

    框架的访问级别

    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.

    当你开发一个框架时,把该框架中那些公开的接口标记为open或public的,以便其他模块可以浏览和访问。

    这些公开的接口就是这个框架的API.

    单元测试目标的访问级别

    When you write an app with a unit test target, the code in your app needs to be made available to that module in order to be tested. By default, only entities marked as open or public are accessible to other modules. However, a unit test target can access any internal entity, if you mark the import declaration for a product module with the @testable attribute and compile that product module with testing enabled.

    当你写一个有单元测试目标的app时,你的代码需要被那个模块访问,以便用于测试。默认地,只有open或public的实体能被其他模块访问。但是,如果你用@testable标记那个导入的产品模块声明,并用testing enabled 编译那个产品模块,一个单元测试目标可以访问任何internal实体。

    访问权限语法

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

    为一个实体定义访问权限,只需把open,public,internal,fileprivate,或者private中的一个写在实体前就可以了:

    public class SomePublicClass {}
    internal class SomeInternalClass {}
    fileprivate class SomeFilePrivateClass {}
    private class SomePrivateClass {}
     
    public var somePublicVariable = 0
    internal let someInternalConstant = 0
    fileprivate func someFilePrivateFunction() {}
    private func somePrivateFunction() {}
    

    Unless otherwise specified, the default access level is internal, as described in Default Access Levels. This means that SomeInternalClass and someInternalConstant can be written without an explicit access-level modifier, and will still have an access level of internal:

    除非另外指定,否则默认的访问级别就是internal。这表示SomeInternalClass 和someInternalConstant可以不需要特别的指定访问权限:

    class SomeInternalClass {}              // implicitly internal
    let someInternalConstant = 0            // implicitly internal
    

    自定义类型

    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. For example, if you define a file-private class, that class can only be used as the type of a property, or as a function parameter or return type, in the source file in which the file-private class is defined.

    如果你想为一个自定义类型指定一个显式的访问级别,需要在定义此类别的时候加上访问权限修饰符。然后这个新的类型就可以在它的访问权限内被使用了。比如,如果你定义了一个fileprivate类,那个类只能在它被定义的源文件中用作一个属性的类型,或作为一个 函数的参数或返回类型。

    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.

    一个类型的访问权限级别也会影响此类型的默认访问权限的成员(他的属性,方法,初始化方法,下标脚本)。如果你定义了一个类型的访问级别为private或fileprivate,它的成员的默认访问级别也会变成private或fileprivate。如果你定义了一个类型的访问级别为internal或public(或者用默认的访问级别internal),那么此类型的成员的默认访问级别是internal。

    public class SomePublicClass {                  // 显式的 public 类
        public var somePublicProperty = 0            // 显式的 public 类成员
        var someInternalProperty = 0                 // 隐式的 internal 类成员
        fileprivate func someFilePrivateMethod() {}  // 显式的 file-private 类成员
        private func somePrivateMethod() {}          // 显式的 private 类成员
    }
    
    class SomeInternalClass {                       // 隐式的 internal 类
        var someInternalProperty = 0                 // 隐式的 internal 类成员
        fileprivate func someFilePrivateMethod() {}  // 显式的 file-private 类成员
        private func somePrivateMethod() {}          // 显式的 private 类成员
    }
    
    fileprivate class SomeFilePrivateClass {        // 显式的 file-private 类
        func someFilePrivateMethod() {}              // 隐式的 file-private 类成员
        private func somePrivateMethod() {}          // 显式的 private 类成员
    }
    
    private class SomePrivateClass {                // 显式的 private 类
        func somePrivateMethod() {}                  // 隐式的 private 类成员
    }
    

    元组类型

    The access level for a tuple type is the most restrictive access level of all types used in that tuple. For example, if you compose a tuple from two different types, one with internal access and one with private access, the access level for that compound tuple type will be private.

    一个元组类型的访问级别就是该元组中的所有类型中最严格的访问级别。比如,如果你用两个不同的类型组成一个元组,一个是internal的,一个是private的,那么此元组的访问级别就是private的。

    函数类型

    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.

    函数的访问级别是此函数的参数类型和返回类型的访问级别中最严格的那个访问级别。如果此函数的访问级别无法匹配上下文,你就必须指定此函数的访问级别。

    The example below defines a global function called someFunction(), without providing a specific access-level modifier for the function itself. You might expect this function to have the default access level of “internal”, but this is not the case. In fact, someFunction() will not compile as written below:

    下面的例子定义了一个全局函数someFunction(),此函数没有一个指定的访问级别修饰符。你或许以为这个函数的默认访问级别是internal的,但是并非如此。事实上,下面的someFunction()无法编译:

    func someFunction() -> (SomeInternalClass, SomePrivateClass) {
        // function implementation goes here
    }
    

    The function’s return type is a tuple type composed from two of the custom classes defined above in Custom Types. One of these classes was defined as “internal”, and the other was defined as “private”. Therefore, the overall access level of the compound tuple type is “private” (the minimum access level of the tuple’s constituent types).

    这个函数的返回类型是一个元组—有两个自定义类(在自定义类型那一节中定义)组合而成。其中一个类是internal的,另一个是private的,因此这个元组的访问级别是private.

    Because the function’s return type is private, you must mark the function’s overall access level with the private modifier for the function declaration to be valid:

    由于这个函数的返回类型是private的,因此你必须标记此函数的访问级别为private:

    private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
        // function implementation goes here
    }
    

    It is not valid to mark the definition of someFunction() with the public or internal modifiers, or to use the default setting of internal, because public or internal users of the function might not have appropriate access to the private class used in the function’s return type.

    如果你把someFunction()标示为public或internal的话,或是使用默认的internal,那将是无效的,因为public或internal的函数用户或许无法获取此函数的返回类型用到的private类。

    枚举类型

    The individual cases of an enumeration automatically receive the same access level as the enumeration they belong to. You cannot specify a different access level for individual enumeration cases.

    枚举中的各个case自动地获取跟该枚举一样的访问级别。你不能为它们指定一个不同的访问级别。

    In the example below, the CompassPoint enumeration has an explicit access level of “public”. The enumeration cases north, south, east, and west therefore also have an access level of “public”:

    下面的例子中,枚举CompassPoint有一个显式的访问级别public.枚举中的各个值north,south,east,和west的访问级别也就是public:

    public enum CompassPoint {
        case north
        case south
        case east
        case west
    }
    

    原始值与关联值

    The types used for any raw values or associated values in an enumeration definition must have an access level at least as high as the enumeration’s access level. You cannot use a private type as the raw-value type of an enumeration with an internal access level, for example.

    枚举中的原始值或关联值的类型的访问级别至少跟该枚举的访问级别一样高。比如,如果一个枚举的访问级别是internal,那么原始值的访问级别就不能是private。

    嵌套类型

    Nested types defined within a private type have an automatic access level of private. Nested types defined within a file-private type have an automatic access level of file private. Nested types defined within a public type or an internal type have an automatic access level of internal. If you want a nested type within a public type to be publicly available, you must explicitly declare the nested type as public.

    private类型内定义的嵌套类型的访问级别为private。file-private类型内定义的嵌套类型的访问级别是file private。public类型内定义的嵌套类型的访问级别是internal。如果你想让public内定义的嵌套类型的访问级别为public,那你需要显式地指定该嵌套类型为public。

    继承

    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—for example, you cannot write a public subclass of an internal superclass.

    你可以继承当前的访问上下文可以访问的任何类。子类的访问级别不能比它的父类更高—比如,你不能用一个public的子类继承一个internal的父类。

    In addition, you can override any class member (method, property, initializer, or subscript) that is visible in a certain access context.

    在实际开发中,在一个特定的访问上下文中可见的任何类成员(方法,属性,初始化方法,或下标脚本), 你都可以重写。

    An override can make an inherited class member more accessible than its superclass version. In the example below, class A is a public class with a file-private method called someMethod(). Class B is a subclass of A, with a reduced access level of “internal”. Nonetheless, class B provides an override of someMethod() with an access level of “internal”, which is higher than the original implementation of someMethod():

    重写可以使得继承的类成员比它的父类版本更容易访问(more accessible).在下面的例子中,类A是一个public类,有一个file-private的方法someMethod()。类B是A的一个子类,访问级别为internal。类B重写了someMethod()方法,其访问级别为internal,比父类的原始实现的访问级别更高:

    public class A {
        fileprivate func someMethod() {}
    }
     
    internal class B: A {
        override internal func someMethod() {}
    }
    

    It is even valid for a subclass member to call a superclass member that has lower access permissions than the subclass member, as long as the call to the superclass’s member takes place within an allowed access level context (that is, within the same source file as the superclass for a file-private member call, or within the same module as the superclass for an internal member call):

    子类成员调用一个访问权限更低的父类成员也是有效的,只要这个调用放生在允许的访问级别上下文(即是,在同一个源文件中,一个file-private成员调用父类,或者在同一个模块中,internal成员调用父类)

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

    Because superclass A and subclass B are defined in the same source file, it is valid for the B implementation of someMethod() to call super.someMethod().

    因为 父类A和子类B定义在同一个源文件内,所以在B的someMethod()方法内调用super.someMethod()是有效的。

    常量,变量,属性和下标脚本

    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, for example. Similarly, a subscript cannot be more public than either its index type or return type.

    一个常量,变量,或者属性的访问级别不能比它们的类型的访问级别更高。一个private类型不能有一个public的属性。同样的,下标脚本的访问级别既不能高于它的下标类型也不能高于它的返回类型的访问级别。

    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:

    如果一个常量,变量,属性或下标脚本被一个private类型使用,此常量,变量,属性或下标脚本必须标记为private:

    private var privateInstance = SomePrivateClass()
    
    

    getters 和 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.

    常量,变量,属性和下标脚本的getter和setter方法的访问级别跟它们所属的常量,变量,属性和下标脚本相同。

    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.

    你可以把setter的访问级别设置得比它对应的getter的访问级别更低,来限制该变量,属性或下标脚本的读写范围。你只需要在var或subscript前加上 fileprivate(set),private(set), 或者 internal(set)就可以了:

    The example below defines a structure called TrackedString, which keeps track of the number of times a string property is modified:

    下面的例子定义了一个结构TrackedString,该结构记录了一个string属性被修改的次数:

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

    The TrackedString structure defines a stored string property called value, with an initial value of "" (an empty string). The structure also defines a stored integer property called numberOfEdits, which is used to track the number of times that value is modified. This modification tracking is implemented with a didSet property observer on the value property, which increments numberOfEdits every time the value property is set to a new value.

    TrackedString结构定义了一个存储string属性value,初始值为""(一个空字符串)。此结构还定义了一个存储integer属性numberOfEdits,用于跟踪value被修改的次数。这个功能的实现是在value的 didSet属性观察者里,每次value属性被设置为一个新的值,就增加numberOfEdits的值。

    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 structure. This enables TrackedString to modify the numberOfEdits property internally, but to present the property as a read-only property when it is used outside the structure’s definition—including any extensions to TrackedString.

    结构TrackedString和value属性没有显式的声明访问级别,因此它们都是默认的访问级别internal。但是numberOfEdits属性的访问级别标记上了private(set),这表明此属性的getter的访问级别为internal的,但是只有在TrackedString结构的内部,此属性才是可设置的(settable).这使得TrackedString可以在内部修改numberOfEdits属性,但是,当你在此结构定义的外部(包括TrackedString的拓展)使用它时,此属性对外是只读属性。

    If you create a TrackedString instance and modify its string value a few times, you can see the numberOfEdits property value update to match the number of modifications:

    如果你创建了一个TrackedString实例,并修改了几次它的字符串value,你可以看到numberOfEdits属性的值会更新为修改的次数:

    var stringToEdit = TrackedString()
    stringToEdit.value = "This string will be tracked."
    stringToEdit.value += " This edit will increment numberOfEdits."
    stringToEdit.value += " So will this one."
    print("The number of edits is \(stringToEdit.numberOfEdits)")
    // Prints "The number of edits is 3"
    

    Although you can query the current value of the numberOfEdits property from within another source file, you cannot modify the property from another source file. This restriction protects the implementation details of the TrackedString edit-tracking functionality, while still providing convenient access to an aspect of that functionality.

    虽然你可以在别的源文件内查询到numberOfEdits属性的当前值,但是你不能在别的源文件内修改它。这个限制既保护了TrackedString的内部实现,还保证了访问的便利。

    Note that you can assign an explicit access level for both a getter and a setter if required. The example below shows a version of the TrackedString structure in which the structure is defined with an explicit access level of public. The structure’s members (including the numberOfEdits property) therefore have an internal access level by default. You can make the structure’s numberOfEdits property getter public, and its property setter private, by combining the public and private(set) access-level modifiers:

    注意,如果需要的话,你可以为getter和setter指定一个显式的访问级别。下面的例子展示了TrackedString结构的另一个版本,这个版本中TrackedString被定义为public的。结构的成员(包括numberOfEdits属性)因此有一个默认的访问级别internal。你可以设numberOfEdits属性的getter为public的,setter为private的,只需要结合public和private(set):

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

    初始化方法

    Custom initializers can be assigned an access level less than or equal to the type that they initialize. The only exception is for required initializers (as defined in Required Initializers). A required initializer must have the same access level as the class it belongs to.

    自定义的初始化方法的访问级别可以比它要初始化的类型的访问级别更低。唯一的例外是必须的初始化方法.一个必须的初始化方法的访问级别必须跟它属于的类的访问级别一样。

    As with function and method parameters, the types of an initializer’s parameters cannot be more private than the initializer’s own access level.

    对于函数和方法参数,初始化方法参数的类型不能比初始化方法等访问级别更低。

    默认初始化方法

    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.

    swift为结构自动提供了一个没有参数的默认初始化方法,对于为其所有属性都提供了默认值但没有提供初始化方法的基类,swift也自动提供一个没有参数的默认初始化方法。

    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.

    默认初始化方法的访问级别跟它要初始化的类型的访问级别一样,除非那个类型是public的。对于public的类型,它的默认初始化方法是internal的。如果你想在其他模块内初始化一个public类型—该类型有一个没有参数的初始化方法,那么你必须在该类型的定义中显式的提供一个没有参数的初始化方法。

    结构类型的默认逐一成员初始化方法

    The default memberwise initializer for a structure type is considered private if any of the structure’s stored properties are private. Likewise, if any of the structure’s stored properties are file private, the initializer is file private. Otherwise, the initializer has an access level of internal.

    结构类型的默认逐一成员初始化方法是private的,如果该结构的任意存储属性都是private的话。如果该结构的任意存储属性都是file private的,那么它的默认逐一成员初始化方法也是file private的。否则,该初始化方法的访问级别是internal。

    As with the default initializer above, if you want a public structure type to be initializable with a memberwise initializer when used in another module, you must provide a public memberwise initializer yourself as part of the type’s definition.

    至于上面说的默认初始化方法,如果你想在其他的模块中初始化一个有逐一成员初始化方法的public的结构类型的话,你必须在该类型的定义内提供一个public的逐一成员初始化方法。

    协议

    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.

    协议内的各项要求条件的访问级别都自动的设为该协议的访问级别。你不能为协议内的要求条件指定一个不同于该协议的访问级别。这确保了协议内的要求条件在遵循该协议的任意类型中都是可见的。

    协议继承

    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.

    如果你定义了一个新的协议,它继承自一个已有协议,这个新协议的访问级别最多只能跟它继承的协议的访问级别一样。比如,你不能用一个public的协议继承一个internal的协议。

    协议一致性(Protocol Conformance)

    A type can conform to a protocol with a lower access level than the type itself. For example, you can define a public type that can be used in other modules, but whose conformance to an internal protocol can only be used within the internal protocol’s defining module.

    一个类型可以遵循一个访问级别比它本身访问级别低的协议。比如,你可以定义一个public类型,该类型可以在其他模块使用,但是它可以遵循一个internal协议,该协议只能在定义它的模块内使用。

    The context in which a type conforms to a particular protocol is the minimum of the type’s access level and the protocol’s access level. If a type is public, but a protocol it conforms to is internal, the type’s conformance to that protocol is also internal.

    一个类型遵循一个特定协议的上下文是该类型的访问级别与该协议的访问级别的最小值。如果一个类型是public的,但是它遵循的协议是internal的,那么这个类型在遵循该协议后也是internal的

    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”.

    当你定义一个类型或拓展一个类型去遵循一个协议的时候,你必须保证该类型对协议的每个要求的实现的访问级别至少跟遵循了该协议的类型的访问级别一致。比如,如果一个public类型遵循了一个internal协议,该类型对该协议的实现也必须至少是internal的。

    拓展

    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.

    你可以在类,结构或枚举是可见的访问上下文中拓展一个类,结构或枚举。任何在拓展中添加的类型成员的访问级别都跟原来的类型成员的访问级别一致。如果你拓展了一个public或internal类型,任何你添加的新的类型成员都有一个默认的访问级别internal。如果你拓展一个file private类型,任何你添加的新的类型成员都有一个默认的访问级别file private。如果你拓展一个private类型,任何你添加的新的类型成员都有一个默认的访问级别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. This new default can still be overridden within the extension for individual type members.

    你可以为拓展的所有成员显式的标记一个访问级别作为默认访问级别。这个新的默认访问级别还能被拓展中的类型成员重写。

    协议的拓展(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.

    如果一个拓展遵循了某个协议,那么你就不能为该拓展显式的指定访问级别了。该拓展实现的协议的每个要求的访问级别将是 该协议的访问级别。

    范型

    The access level for a generic type or generic function is the minimum of the access level of the generic type or function itself and the access level of any type constraints on its type parameters.

    一个范型类型或范型函数的访问级别是该范型类型,或范型函数本身,和它的类型参数的类型限制的访问级别中最低的那个。

    类型别名

    Any type aliases you define are treated as distinct types for the purposes of access control. A type alias can have an access level less than or equal to the access level of the type it aliases. For example, a private type alias can alias a private, file-private, internal, public, or open type, but a public type alias cannot alias an internal, file-private, or private type.

    你定义的任何类型别名都被视作不同的类型。一个类型别名的访问级别可以低于或等于这个类型的访问级别。比如,一个private的类型别名可以做private,file private,internal,public,open类型的别名,但是一个public的类型别名就不能做一个internal,file private,private类型的别名。

    相关文章

      网友评论

        本文标题:swift入门23 访问控制

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