一、Swift的访问控制

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

  1. 模块
    指的是Framework或App 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()
}

iOS学习笔记49-Swift(九)访问控制的更多相关文章

  1. iOS学习笔记-精华整理

    iOS学习笔记总结整理 一.内存管理情况 1- autorelease,当用户的代码在持续运行时,自动释放池是不会被销毁的,这段时间内用户可以安全地使用自动释放的对象.当用户的代码运行告一段 落,开始 ...

  2. iOS学习笔记总结整理

    来源:http://mobile.51cto.com/iphone-386851_all.htm 学习IOS开发这对于一个初学者来说,是一件非常挠头的事情.其实学习IOS开发无外乎平时的积累与总结.下 ...

  3. iOS学习笔记-自定义过渡动画

    代码地址如下:http://www.demodashi.com/demo/11678.html 这篇笔记翻译自raywenderlick网站的过渡动画的一篇文章,原文用的swift,由于考虑到swif ...

  4. iOS学习笔记——AutoLayout的约束

    iOS学习笔记——AutoLayout约束 之前在开发iOS app时一直以为苹果的布局是绝对布局,在IB中拖拉控件运行或者直接使用代码去调整控件都会发上一些不尽人意的结果,后来发现iOS在引入了Au ...

  5. IOS学习笔记25—HTTP操作之ASIHTTPRequest

    IOS学习笔记25—HTTP操作之ASIHTTPRequest 分类: iOS2012-08-12 10:04 7734人阅读 评论(3) 收藏 举报 iosios5网络wrapper框架新浪微博 A ...

  6. IOS学习笔记之关键词@dynamic

    IOS学习笔记之关键词@dynamic @dynamic这个关键词,通常是用不到的. 它与@synthesize的区别在于: 使用@synthesize编译器会确实的产生getter和setter方法 ...

  7. iOS学习笔记10-UIView动画

    上次学习了iOS学习笔记09-核心动画CoreAnimation,这次继续学习动画,上次使用的CoreAnimation很多人感觉使用起来很繁琐,有没有更加方便的动画效果实现呢?答案是有的,那就是UI ...

  8. 【Unity Shaders】学习笔记——SurfaceShader(九)Cubemap

    [Unity Shaders]学习笔记——SurfaceShader(九)Cubemap 如果你想从零开始学习Unity Shader,那么你可以看看本系列的文章入门,你只需要稍微有点编程的概念就可以 ...

  9. iOS学习笔记之Category

    iOS学习笔记之Category 写在前面 Category是类别(也称为类目或范畴),使用Category,程序员可以为任何已有的类添加方法.使用类别可以对框架提供的类(无法获取源码,不能直接修改) ...

  10. iOS学习笔记之ARC内存管理

    iOS学习笔记之ARC内存管理 写在前面 ARC(Automatic Reference Counting),自动引用计数,是iOS中采用的一种内存管理方式. 指针变量与对象所有权 指针变量暗含了对其 ...

随机推荐

  1. 中国各运营商(电信、联通、移动、铁通)IP地址段

    除此电信.联通.移动.铁通之外还有教育网.科技网.广电.长城.广电…… 表格下载: http://files.cnblogs.com/files/xiaohi/中国IP网段.zip 以上资料参考: h ...

  2. stixel-world跑在kitti数据集

    kitti数据集中每一帧的Calibration不同,每一帧都存储了4个相机的Calibration http://ww.cvlibs.net/publications/Geiger2013IJRR. ...

  3. VIM+ctags+cscope用法

    使用vim + cscope/ctags,就能够实现Source Insight的功能,可以很方便地查看分析源代码.   关键词: vim, cscope, ctags, tags   1. 查看vi ...

  4. vs 2012打开vs2013的sln

    Project -> Properties -> General -> Platform Toolset (as IInspectable correctly commented)

  5. Windows系统安装docker

    下载安装包 官网 点击 Get Started ,打开入门页面,往下拉,找到 Download for Windows 打开 下载页面 ,点击 Please Login To Download ,要注 ...

  6. 沙盒(SandBox)

    iOS 应用沙盒机制就是指 iOS 应用程序只能在为该程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文本 ...

  7. logging console not work

    配置 log 信息传输到控制台 参考官网:https://docs.djangoproject.com/en/2.1/topics/logging/ By default, this config o ...

  8. 自然数的拆分(DFS)

    题目描述: 任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和. 输入格式: 待拆分的自然数n. 输出格式: 若干数的加法式子. 样例输入: 7 样例输出: 1+1+1+1+1+1+1 1 ...

  9. 了解swagger

    https://blog.csdn.net/i6448038/article/details/77622977 随着互联网技术的发展,现在的网站架构基本都由原来的后端渲染,变成了:前端渲染.先后端分离 ...

  10. GTX 750等低配显卡如何玩转Deepfakes?

    这里说的Deepfakes软件还是DeepFaceLab,人工智能换脸,是使用深度学习方法来实现的.而深度学习程序对电脑配置要求是非常高的,尤其是跑模型这个环节.很多低配电脑,根本就跑步起来.比如像G ...