在Swift中,有一种结构extension,类似于OC中的Category分类,非常适合于对代码进行管理
同时,常用的访问修饰符有public、internal、private,而对于这三个访问修饰符,对extension的影响是各不一样的
在本文中,我将对同一文件下和不同文件下的extension、在本类和其他类调用,共四种情况进行分别介绍。
在介绍前,我先创建了一个非常简单的iOS项目,并新建了一个Person类和Person类的extension文件,如下图:
其中,Person类的代码如下:
Person+Extension文件中的代码如下:
从上面的代码可以看到,在Person类本文件中的extension创建了两个函数,分别是getAge()和getGender()
在Person+Extension文件中创建了两个函数,叫sayHello()和sayGoodBye()
而具体的测试,将分别在Person本类的printSomething()和ViewController类的viewDidLoad()两个函数中分别进行
1、internal
internal是一个作用域介于public和private之间的访问修饰符,也是swift中默认的访问修饰符,通常是直接省略的
internal既不像public那么有开放性,也不像private那么封闭
a.同一文件下的extension,在其他类中调用:
在ViewController文件中直接调用Person类本文件extension中的方法如下:
可以很清楚的看到,是可以很直接的调用到这个函数的
b.不同文件下的extension,在其他类中调用:
接下来调用Person+Extension的sayHello()函数:
在这种情况下,非同一文件下的extension中的函数也是可以调用到的
c.同一文件下的extension,在本类中调用:
在Person类中测试结果如下:
d.不同文件下的extension,在本类中调用:
在Person类中测试结果如下:
结论:在internal或无修饰符情况下,不论extension中的函数和类文件是否在同一文件中,均可以顺利调用执行
2、private
private在各个编程语言中都表示私有方法/函数,在此我们均尝试一下使用private后两种情况下的extension函数
在开始前先
a.同一文件下的extension,在其他类中调用:
根据测试,即使是extension与类在同一文件中,在ViewController中也无法调用到被private修饰的函数getGender()
b.不同文件下的extension,在其他类中调用:
测试后结果显示,extension与类在不同文件中的情况下,ViewController同样无法调用到被private修饰的函数sayGoodBye()
c.同一文件下的extension,在本类中调用:
经测试,在此情况下,本类可以调用到与类在同一文件下的extension中被private修饰的函数
d.不同文件下的extension,在本类中调用:
测试结果显示,与类不在同一文件的extension中的被private修饰的函数,即使在本类中也无法调用
结论:在private修饰的extension函数中,仅有与类在同一文件的可以被顺利调用,其他情况下均无法被调用
3、public
public因其开放性,在任何位置均可以调用被public修饰的方法/函数,因此通常用于全局性的变量、属性或者方法。
在测试前将原来没有使用访问修饰符的getAge()和sayHello()函数前分别加上public修饰符。
而实际测试中,直接在方法前加上public修饰符会提示警告如下:
针对这种情况,Xcode编译器建议将public替换为internal,为解决这个问题,必须在类声明前也加上public才可以
即证明:只有在public修饰的类中才可以存在被public修饰的函数
经修改后继续测试,测试结果依次如下:
a.同一文件下的extension,在其他类中调用:
b.不同文件下的extension,在其他类中调用:
c.同一文件下的extension,在本类中调用:
d.不同文件下的extension,在本类中调用:
结论:被public修饰的函数,不论是否与本类在同一文件,在本类和其他类中均可以被调用
综上所有结论如下:
访问修饰符 | 同一文件,其他类调用 | 不同文件,其他类调用 | 同一文件,本类调用 | 不同文件,本类调用 |
internal | 可以被调用 | 可以被调用 | 可以被调用 | 可以被调用 |
private | 不可以 | 不可以 | 可以被调用 | 不可以 |
public | 可以被调用 | 可以被调用 | 可以被调用 | 可以被调用 |
表格注释:同一文件和不同文件仅代表函数所在extension是否与所在类是同一个文件
参考文章:https://github.com/bboyfeiyu/iOS-tech-frontier/blob/master/issue-4/Swift扩展的三个微妙细节.md