zoukankan      html  css  js  c++  java
  • iOS学习笔记49-Swift(九)访问控制

    一、Swift的访问控制

    Swift中的访问控制模型基于模块源文件这两个概念

    1. 模块
      指的是FrameworkApp bundle。在Swift中,可以用import关键字引入自己的工程。
    2. 源文件
      指的是Swift中的Swift File,就是编写Swift代码的文件,它通常是属于某一个模块。
    Swift提供了三种不同的访问级别:
    • Public:【使用public修饰】【范围大】
      可以访问当前模块及其他模块中的任何实体(通常用于Framework
    • Internal:【使用internal修饰】【范围中】
      可以访问当前模块中的任何实体,但是在模块外无法访问,这是所有实体的默认访问级别(通常在一个单目标Application中不需要自行设置访问级别)
    • Private:【使用private修饰】【范围小】
      只能访问当前源文件中的实体,用作隐藏某些功能的实现细节

    访问级别从低到高:Private < Internal < Public

    访问控制的使用规则挺多的,我这里进行了概括:
    1. 【成员(属性和方法) <= 类】
    2. 【(常量、变量、属性、下标脚本) <= 类型】
    3. 【Setter <= Getter】
    4. 【required方法 == 类】【默认逐一构造函数 <= 所有成员】
    5. 【子类 <= 父类】【子协议 <= 父协议】
    6. 子类重写父类成员修改访问范围
    7. 【协议成员 == 协议】【类 >= 协议】【协议实现 >= 协议要求】
    8. 【元组 = Min(所有元素类型)】
    9. 【函数 = Min(参数类型,返回值类型)】
    10. 【枚举成员 == 枚举】【(原始值,关联值) >= 枚举】
    11. 【泛型类型 = Min(类类型,泛型参数)】
    12. 【类型别名 <= 原类型】

    二、访问控制使用规则详解

    1.【成员(属性和方法) <= 类】
    /* 
        1.【成员(属性和方法) <= 类】
        如果你将类申明为private类,那么该类的所有成员的默认访问级别也会成为private
        如果你将类申明为public或者internal类,那么该类的所有成员默认访问级别是internal。
    */
    public class SomePublicClass {          // 显示的public类
        public var somePublicProperty = 0    // 显示的public类成员
        var someInternalProperty = 0         // 隐式的internal类成员
        internal var someInternalProperty2 = 0 //显示的internal类成员
        private func somePrivateMethod() {}  // 显示的private类成员
    }
    internal class SomeInternalClass {        // 显示的internal类
        var someInternalProperty = 0         // 隐式的internal类成员
        private func somePrivateMethod() {}  // 显示的private类成员
        //Error:-> public var somePublicProperty = 0 
        
    }
    private class SomePrivateClass {        // 显示的private类
        var somePrivateProperty = 0          // 隐式的private类成员
        func somePrivateMethod() {}          // 隐式的private类成员
        //Error:-> public var somePublicProperty = 0 
        //Error:-> internal var someInternalProperty = 0
    }
    2.【(常量、变量、属性、下标脚本) <= 类型】
    /* 2.【(常量、变量、属性、下标脚本) <= 自己类型】 */
    private let somePrivate1 = SomePrivateClass() //变量为private <= 类型为private
    private let somePrivate2 = SomeInternalClass()//变量为private <= 类型为internal
    private let somePrivate3 = SomePublicClass()//变量为private <= 类型为public
    //Error:internal let someInternal1 = SomePrivateClass() //变量internal大于类型private,错误
    internal let someInternal2 = SomeInternalClass()//变量为internal <= 类型为internal
    internal let someInternal3 = SomePublicClass()//变量为internal <= 类型为public
    //Error:public let somePublic1 = SomePrivateClass() //变量public大于类型private,错误
    //Error:public let somePublic2 = SomeInternalClass() //变量public大于类型internal,错误
    public let somePublic3 = SomePublicClass()//变量为public <= 类型为public
    3.【Setter <= Getter】
    /* 3.【setter <= getter】,private(set)修饰将setter权限设置为private */
    /* 
        这个规定适用于用作存储的属性或用作计算的属性。
        即使你不明确的申明存储属性的Getter、Setter,
        Swift也会隐式的为其创建Getter和Setter,用于对该属性进行读取操作。
    */
    public class SetterPrivateClass {//该类可以在任何模块中使用
        private(set) var value = 0 //设置存储属性的setter为private
        //设置计算属性的setter属性为private
        private(set) var setPrivateProperty:Int {
            set{//此时setter为private,也就是只能在本文件中使用,其他文件无法使用
                value = newValue + 1
            }
            get{//getter默认为internal
                return value + 1
            }
        }
    }
    4.【required方法 == 类】【默认逐一构造函数 <= 所有成员】
    /* 4.【required修饰的方法 == 类】,(结构体)【默认逐一构造函数 <= 所有成员】 */
    protocol RequiredTestProtocol {
        //初始化构造器要求
        init(aprot: Int)
    }
    public class RequiredTestClass: RequiredTestProtocol {
        var aprot: Int //默认为internal
        //实现协议的初始化要求时,必须使用required关键字确保子类必须也得实现这个构造器
        public required init(aprot: Int) {//此时必须设置为public,因为默认是internal的
            self.aprot = aprot
        }
    }
    //该结构体的默认逐一构造方法为private,但默认构造方法还是internal
    public struct StructInitTest{
        private var somePrivateProperty = 0
        internal var someInternalProperty = 0
        public var somePublicProperty = 0
    }
    5.【子类 <= 父类】【子协议 <= 父协议】
    /* 5.【子类 <= 父类】,【子协议 <= 父协议】 */
    private class PrivateSuperClass {  } //private父类
    internal class InternalSuperClass {  }//internal父类
    public class PublicSuperClass {  }//public父类
    private class PrivateSubClass1:PrivateSuperClass {  } //子类private <= private父类
    private class PrivateSubClass2:InternalSuperClass {  } //子类private <= internal父类
    private class PrivateSubClass3:PublicSuperClass {  } //子类private <= public父类
    
    //Error:internal class InternalSubClass1:PrivateSuperClass {  } //子类internal大于private父类,错误
    internal class InternalSubClass2:InternalSuperClass {  } //子类internal <= internal父类
    internal class InternalSubClass3:PublicSuperClass {  } //子类internal <= public父类
    
    //Error:public class PublicSubClass1:PrivateSuperClass {  } //子类public大于private父类,错误
    //Error:public class PublicSubClass2:InternalSuperClass {  } //子类public大于internal父类,错误
    public class PublicSubClass3:PublicSuperClass {  } //子类public <= public父类
    6. 子类重写父类成员修改访问范围
    /* 6.不违反前面规则,子类可以通过重写父类方法来修改访问权限范围 */
    public class OverrideSuperClass {
        private func someMethod() {}
    }
    internal class OverrideSubClass: OverrideSuperClass {
        override internal func someMethod() {
            super.someMethod()//子类和父类在同一个源文件中,所以可以访问super的someMethod()方法
        }
    }
    7.【协议成员 == 协议】【类 >= 协议】【协议实现 >= 协议要求】
    /* 7.【协议所有必须实现的成员 == 协议】,【类 >= 协议】,【协议实现 >= 协议要求】 */
    internal protocol InternalProtocol {
        //协议成员不可以添加访问控制关键字,默认等于协议的访问权限范围
        var someProperty:Int { get set }
        func someMethod()
    }
    //类必须大于或等于要遵循的协议
    public class ProtocolTestClass:InternalProtocol {
        //Error:-> private var someProperty = 0 //协议实现必须大于或等于协议要求
        public var someProperty = 0
        internal func someMethod() {
            print("ProtocolTestClass someMethod")
        }
    }
    8.【元组 = Min(所有元素类型)】
    /* 8.【元组 = Min(所有元素类型)】,注意是类型而不是变量 */
    private var privateValue =  SomePrivateClass() //注意,看类型访问级别而不是变量访问级别
    var internalValue =  SomeInternalClass()
    var publicValue = SomePublicClass() //这里变量是internal的,但类型是public的
    private let privateTupleValue = (privateValue, internalValue, publicValue)
    internal let internalTupleValue = (internalValue, internalValue, publicValue)
    public let publicTupleValue = (publicValue, publicValue, publicValue)
    9.【函数 = Min(参数类型,返回值类型)】
    /* 9.【函数 = Min(参数类型,返回值类型)】 */
    private func someFunction(value:SomeInternalClass) -> SomePrivateClass {
        //函数体
        return SomePrivateClass()
    }
    10.【枚举成员 == 枚举】【(原始值,关联值) >= 枚举】
    /* 10.【枚举成员 == 枚举】,枚举成员没法单独设置访问级别,【(原始值,关联值) >= 枚举】 */
    private enum PrivateEnum {
        case PrivateEnumCase( SomePrivateClass )
        case InternalEnumCase( SomeInternalClass )
        case PublicEnumCase( SomePublicClass )
    }
    internal enum InternalEnum {
        //Error:-> case PrivateEnumCase( SomePrivateClass ) //关联值必须大于枚举
        case InternalEnumCase( SomeInternalClass )
        case PublicEnumCase( SomePublicClass )
    }
    11.【泛型类型 = Min(类类型,泛型参数)】
    /* 11.【泛型类型 = Min(类类型,泛型参数)】 */
    public class GenericityClass<T> {
        var value = [T]()
        func someFunction(value:T) { }
    }
    private let genericityPrivate = GenericityClass<SomePrivateClass>() //泛型类型为private
    internal let genericityInternal = GenericityClass<SomeInternalClass>() //泛型类型为internal
    public let genericityPublic = GenericityClass<SomePublicClass>() //泛型类型为public
    //Error:public let genericityInternal = GenericityClass<SomeInternalClass>() //泛型类型为internal
    12.【类型别名 <= 原类型】
    /* 12.【类型别名 <= 原类型】 */
    //包含类型别名的类,遵循【成员<=类】
    public class MyClass {
        //声明一个类型别名,类型别名是一个为已存在类型定义的一个可选择的名字
        private typealias privateName1 = SomePrivateClass
        private typealias privateName2 = SomeInternalClass
        private typealias privateName3 = SomePublicClass
        //internal的类型别名可以是internal、public的类型,不可以是private类型
        //Error:-> internal typealias internalName1 = SomePrivateClass
        internal typealias internalName2 = SomeInternalClass
        internal typealias internalName3 = SomePublicClass
        //public的类型别名只能是public的类型
        //Error:-> public typealias publicName1 = SomePrivateClass
        //Error:-> public typealias publicName2 = SomeInternalClass
        public typealias publicName3 = SomePublicClass
        
        private var someProperty = privateName1()
    }
  • 相关阅读:
    HttpClient调用RestFul接口(post和get方式)
    mysql权限异常
    javascript:用法
    Java哈希值HashCode理解
    Java的CountDownLatch和CyclicBarrier的理解和区别
    Java并发编程与技术内幕:ThreadGroup线程组应用
    面试官: 谈谈什么是守护线程以及作用 ?
    java 成员变量 静态成员变量 方法 静态方法初始化顺序
    【java并发核心一】Semaphore 的使用思路
    threadlocal原理及常用应用场景
  • 原文地址:https://www.cnblogs.com/ming1025/p/6072728.html
Copyright © 2011-2022 走看看