小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
1.访问级别
1.1.open
open的权限无疑是最大的,可以在允许的实体模块,其它模块中访问,并且允许其它模块进行继承和重写。
举个例子:TargetA中有classA,权限是open,TargetB中的classB即可以继承classA,classA的方法,成员变量等也可以被访问。
1.2.public
public和open是差不多的,也是允许在实体模块,其它模块中访问,有一点区别的是,并不允许其它模块进行继承和重写。
举个例子:TargetA中有classA,方法是testA,权限是public,TargetB中有classB,那么在classB中testB方法,就可以初始化var a = classA(),并且调用a.testA()。
1.3.internal
internal只允许在定义的实体模块进行访问,不允许在其它模块中访问。这个也是很多实体默认的权限。
1.4.fileprivate
fileprivate翻译过来就是文件私隐,它只允许在定义的文件中访问。
举个例子:在一个Target中,有classA和classB两个类分别在两个文件,classA当前权限是fileprivate,那么classB是不能访问classA的。如果classA和classB是在同一个文件下,就可以访问。
1.5.private
private只允许在当前定义实体中访问。
举个例子:classA和classB都在同一个文件,classA的权限是private,那classB原理上是不能访问classA的。要访问的话,需要一些情况。这个后面会说到。
2.访问级别的使用准则
一个实体不可以被更低的访问级别的实体定义。
2.1.变量类型的访问级别 >= 变量的访问级别
举个例子:定义一个类 fileprivate class ClassA{},如果定义为internal var classA: ClassA就会报错,权限ClassA的实体类型需要大于变量classA。
2.2.参数类型,返回值类型 >= 函数
举个例子:func testA(_ num: Int) -> Double {},函数的访问级别默认是internal, 参数的num是public,返回值Double也是public。
2.3.父类 >= 子类
相当于说我能访问子类,那么父类也应该要可以访问才对。举个例子:class SupClassA {},子类class ClassA:SupClassA {},父类的默认权限是internal,那么子类就不能为public和open。
3.成员嵌套类型
3.1.类型为private,fileprivate
当类型为private,fileprivate,那么成员的默认类型也是private或fileprivate
举个例子:flieprivate class ClassA { var a = 0 , var b = 0},a和b默认都是fileprivate。
fileprivate class ClassA {
var a = 0
private var b = 0
}
3.2.类型为internal,public
当类型为internal,public,成员的默认类型为internal
public class ClassA {
internal var a = 0
}
4.getter, setter权限
对于读写方面,很多时候我们希望别人读我们的值,而不允许修改我们的值,我们可以这么定义如下:
class ClassA {
private(set) var age: Int = 0
}
5.测试
5.1.例子1
private class Person {}
fileprivate class Student: Person {}
这个例子能不能编译通过???
在这里就可以看出来,能不能通过是看作用域了。
截图1Person的作用域是classA, 所以Student不能继承父类Person。
截图2Person2的作用域是当前文件,Student2的作用域也是当前文件,所以可以继承。
5.2.例子2
private class ClassA {
var age: Int = 0
func testA() {}
}
fileprivate class ClassB {
var classA = ClassA()
func testB() {
classA.age = 2
classA.testA()
}
}
看代码,这个和上面的例子1也是一样的,都可以编译通过,那这时候如果我们对ClassA的age和testA定义为private,这时候还可以访问吗???
直接看结果。
why,为什么呢,按之前我们成员嵌套类型中的说法是,classA是private,子类默认就是private,这时候我们写出来为什么就报错了呢???
换一个说法,在ClassB中,能够定义classA,也可以说明在全局中,ClassA也是相当于fileprivate,里面的age和testA也是fileprivate,如果换成private,就相当于作用域在classA中了,所以就会报错。
这时候我们就可以得出一个结论:直接在全局作用域下定义的private等价于fileprivate。