Swift学习笔记23——访问控制(Access Control)

这篇博客详细介绍了Swift的访问控制机制,包括public、internal和private三种权限,以及在模块、源文件中的应用。强调了访问权限的原则,并讨论了类型、方法、枚举、内部类、子类、属性、构造器、协议、扩展和泛型等在不同访问权限下的规定和限制。

Swift和C++,Java一样,也有访问控制的概念。通过访问权限的控制,我们可以对外隐藏内部的代码细节,防止修改。

Swift的访问控制是基于模块(modules)和源文件(source file)

Swift的模块概念是这样的:

1、一个App bundle,或者一个framework都可以看成一个独立的module。 你可以使用import来引入别的module到你的module中来。

当你将你的代码打包成一个framework,这个framework就是一个module。里面的所有的东西都是属于这个framework,无论你将这个framework引入到别的framework或app中。

2、一个源文件里面虽然可以定义多个类,但是建议一般一个源文件建立一个类。


Swift的访问权限有三个:

1、public    这个权限允许同一个module内部的所有源代码访问,同时允许其他引入了该module的module使用。总的来说就是全开放

2、internal  这个权限允许同一个module内部的所有源代码访问,不允许其他module使用。

3、private   这个权限仅允许同一个source file的代码访问。


Swift的默认访问权限是internal。


public是最高访问权限,而private是最低访问权限。


Swift的权限编程原则:

一、高权限的东西不能包含在低权限的东西里面。

举例:

1、说就是一个public的类型不能定义在一个声明为internal的类型里面。

2、方法的权限不能高于参数和范围值的权限。否则会导致这个方法没法使用。


二、单一app中

一般就用默认的internal就行了。如果你想对其他源文件隐藏,可以使用private。


三、framework中

对于要提供给外边使用的属性,方法。必须使用public权限。其他的可以默认使用internal。如果相对framework里面的其他源文件隐藏,可以使用private。


四、单元测试中

单元测试和我们编写的代码属于不同的module,所以测试模块一般只能访问到public的东西。但是在引入要测试的模块的时候可以加上@testable,这样测试模块就可以访问了。然后要允许被测试的单元可以测试。


示例:

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


给类型定义访问权限的时候,会影响到类型里面的成员(属性,方法,下标,构造器)。

1、将一个类型定义为private后,它里面的成员都是private的。

2、将一个类型定义为public或internal后,它里面的成员还是internal的。如果要某个成员变为public,必须在该成员里面加上public。


Tuple

Tuple的访问权限由tuple成员里面访问权限最小那个决定。


方法

方法的访问权限由方法的参数和返回值中最小权限的那个决定。当方法的权限是private的时候,方法的前面要加上private关键字。


枚举类

枚举类型的成员变量的访问权限决定于枚举类型。例如你定义了一个public的枚举类型,那么它里面的case成员都是public的,不允许单独给每个case成员定义访问权限。

case成员的raw vlaue的值的权限必须大于等于枚举类的访问权限。


内部类

定义在private类型里面的内部类是private权限;定义在public或internal类型里面的内部类默认是internal类型。如果想要定义在public类型里面的内部类变为public的话,需要自己显式给内部类加上public。


子类

子类不能比父类具有更高的访问权限。但是可以重写父类当前能访问到的父类成员,而且可以重写成更高权限的成员。

public class A {
    private func someMethod() {}
}
 
internal class B: A {
    override internal func someMethod() {
        super.someMethod()
    }
}
这里再补充一点,如果父类是public类的,继承之后不加权限修饰符的话,那么这个子类是internal的


属性,常量,变量和下标的访问权限不能超过它所属的类型的权限。


getter和setter方法

这两个方法的访问权限默认和属性的是一样的。但是可以修改setter的权限,可以将setter的权限修改得比属性的权限低,但是不能比属性的权限高。

public class Animal {
    public internal(set) var age: Int = 0
}

构造器

构造器的权限不能大于它所属类型的权限。除了标志有require的构造器之外,这种构造器的权限必须和它所属的类的权限相同。

构造器参数的权限不能低于构造器。


默认构造器

默认构造器的默认权限和类型权限一样。但是如果类型是public,那么默认构造器还是internal的,想要public的无参构造器必须自己实现。

对于结构体的memberwise构造器,想要public的,也要自己实现。


协议

协议的需求的权限和协议权限是一样的,协议是public的,那么需求也是public的。

继承的协议的权限最多只能有父类的权限。例如:不能继承一个internal的协议为一个public协议。


协议的一致性

类型可以实现比自己访问权限低的协议。比如,可以定义一个public的类,它可以实现一个internal的类,并且只能在定义了该协议的模块中使用。

实现了协议的类访问权限是它本身和采用协议中的最低访问权限。也就是说如果一个类是public的级别,实现的是internal的协议,那么采用这个协议之后,该类的访问权限也是internal的。

如果你采用了协议,那么实现协议方法之后,该方法的访问权限遵循协议的访问级别。例如:一个public的类,采用了internal的协议之后,那么该类的实现协议的方法至少也是internal的。


扩展

扩展的默认访问权限由所扩展类型的访问权限决定。

如果你扩展了一个public的类型,那么扩展的成员的默认访问权限就是internal。如果扩展一个private类型,那么扩展的默认访问权限就是private。

当然可以自己给扩展自定义访问权限。但是权限不能超过所扩展的类型。另外可以自己给扩展成员再自定义权限。

如果你是用扩展来实现协议,那么这个扩展不允许自定义权限,它的权限由协议的权限决定。


泛型

泛型分为泛型类型和泛型方法

泛型类型的权限是 泛型类型和泛型参数 之间最小的那个权限。

泛型方法的权限是 泛型方法和泛型参数 之间最小的那个权限。


类型别名

每个类型别名都可以看做是对类型的访问权限的定义。

但是类型别名的权限必须小于或等于要别名的类型。比如一个private的类型别名可以为private,public,internal的类型进行别名;但是一个public的类型别名不能为internal和private的类型进行别名。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值