在Objective-C实例中,数据可以是 public
, protected
或 private
. 例如:
@interface Foo : NSObject
{
@public
int x;
@protected:
int y;
@private:
int z;
}
-(int) apple;
-(int) pear;
-(int) banana;
@end
我没有在Swift参考中找到任何访问修饰符 . 是否可以限制Swift中数据的可见性?
17 回答
As of Swift 3.0.1, there are 4 levels of access,从最高(最少限制)到最低(最具限制性)描述如下 .
1.开放和公开
允许在定义模块(目标)之外使用实体 . 在指定框架的公共接口时,通常使用
open
或public
访问 .但是, open access applies only to classes and class members ,它与
public
access的区别如下:public
类和类成员只能在定义模块(目标)中进行子类化和重写 .open
类和类成员可以在定义模块(目标)内部和外部进行子类化和重写 .2.内部
允许在定义模块(目标)中使用实体 . 在定义应用程序或框架的内部结构时,通常使用
internal
访问 .3. fileprivate
将实体的使用限制在其定义的源文件中 . 当在整个文件中使用这些详细信息时,通常使用
fileprivate
访问来隐藏特定功能的实现细节 .4.私人
限制实体在其附件声明中的使用 . 当这些详细信息仅在单个声明中使用时,通常使用
private
访问来隐藏特定功能的实现细节 .language grammar没有关键字'public','private'或'protected' . 这表明一切都是公开的 . 当然,可能有一些替代方法来指定访问修饰符而没有那些关键字,但我在语言参考中找不到它 .
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html#//apple_ref/doc/uid/TP40014097-CH41-ID3
启动SWIFT 2.2;)
公众
内部
私人
默认为内部
斯威夫特4
正如Swift Documentation - Access Control中所述, Swift 4 有5个访问控制:
open 和 public :可以从导入定义模块的模块's entities and any module'实体访问 .
internal :只能从其模块的实体访问 . 这是默认的访问级别 .
fileprivate 和 private :只能在您定义它们的有限范围内限制访问 .
开放和公共有什么区别?
open 与以前版本的Swift中的public相同,它们允许来自其他模块的类使用和继承它们,即:它们可以从其他模块子类化 . 此外,它们允许来自其他模块的成员使用和覆盖它们 . 他们的模块也采用相同的逻辑 .
public 允许来自其他模块的类使用它们,但不允许继承它们,即:它们不能从其他模块中继承 . 此外,它们允许来自其他模块的成员使用它们,但不要覆盖它们 . 对于他们的模块,它们具有相同的开放逻辑(它们允许类使用和继承它们;它们允许成员使用和覆盖它们) .
fileprivate和private有什么区别?
fileprivate 可以从他们的整个文件中访问 .
private 只能从他们的单一声明和同一文件中的声明的扩展名访问;例如:
Swift 3和Swift 4访问控制有什么区别?
正如SE-0169 proposal中所提到的,Swift 4中唯一的改进是私有访问控制范围已扩展为可以从同一文件中的声明扩展访问;例如:
因此,无需将
myMessage
声明为fileprivate即可在整个文件中访问 .补充说明:如果您遇到与未使用迁移的旧Swift 3项目编译Swift 4相关的问题,您可以查看此问答 .
当谈到在Swift或ObjC(或ruby或java或......)中创建一个"private method"时,这些方法并不是真正的私有 . 它们周围没有实际的访问控制 . 任何提供甚至一点内省的语言都可以让开发人员从课堂外获得这些 Value ,如果他们真的想要的话 .
所以我们在这里真正谈到的是一种定义面向公众的界面的方法,该界面仅提供我们想要的功能,以及"hides"我们认为的其余部分"private" .
用于声明接口的Swift机制是
protocol
,它可以用于此目的 .请记住,协议是一流的类型,可以在任何类型的地方使用 . 而且,当以这种方式使用时,它们只暴露自己的接口,而不是那些接口实施类型 .
因此,只要在参数类型等中使用
MyClass
而不是MyClassImplementation
,它应该只是起作用:有一些直接分配的情况,你必须明确与类型,而不是依靠Swift推断它,但这似乎不是一个交易破坏者:
使用协议这种方式是语义的,相当简洁,我的眼睛看起来很像我们在ObjC中用于此目的的类扩展 .
据我所知,没有关键字'public','private'或'protected' . 这表明一切都是公开的 .
然而,Apple可能期望人们使用“protocols”(世界其他地方称为接口)和factory design pattern来隐藏实现类型的细节 .
无论如何,这通常是一种很好的设计模式;因为它允许您更改 implementation 类层次结构,同时保持 logical 类型系统相同 .
使用协议,闭包和嵌套/内部类的组合,可以使用模块模式的某些内容来隐藏Swift中的信息 . 它不是超级干净或阅读不错但它确实有效 .
例:
innerVal和mysteriousMath在外面使用时隐藏在这里,并试图挖掘进入对象的方式应该导致错误 .
我只是通过阅读Swift文档的方式的一部分,所以如果有一个缺陷请指出来,很想知道 .
从Xcode 6 beta 4开始,Swift具有访问修饰符 . 从发行说明:
隐式默认值为
internal
,因此在应用程序目标中,您可以关闭访问修饰符,除非您希望限制更多 . 在框架目标中(例如,如果您要嵌入框架以在应用程序和共享或今日视图扩展之间共享代码),请使用public
指定要向框架的客户端公开的API .希望为那些想要类似于受保护方法的人节省一些时间:
根据其他答案,swift现在提供了'private'修饰符 - 它是按文件方式而不是按类别定义的,例如Java或C#中的修饰符 . 这意味着如果你想要受保护的方法,你可以使用swift私有方法,如果它们在同一个文件中
创建一个基类来保存'protected'方法(实际上是私有的)
这个类的子类使用相同的方法
在其他文件中,即使您是子类,也无法访问基类方法
例如档案1:
文件2:
}
Swift 3.0 provides five different access controls:
打开
公众
内部
fileprivate
私人
Default Access Levels
如果您没有自己指定显式访问级别,则代码中的所有实体(具有一些特定的例外)都具有内部的默认访问级别 . 因此,在许多情况下,您无需在代码中指定显式访问级别 .
The release note on the topic:
更多信息和详情:The Swift Programming Language (Access Control)
在Beta 6中,文档指出有三种不同的访问权限修饰符:
公众
内部
私人
这三个适用于类,协议,函数和属性 .
有关更多信息,请查看Access Control .
Xcode 6中引入的访问控制机制:
默认情况下将其加入内部,并且不需要指定 . 另请注意,私有说明符 not 在类级别上工作,但在源文件级别上 . 这意味着要使类的某些部分真正私有,您需要将其分成自己的文件 . 这也介绍了一些有关单元测试的有趣案例......
我在上面的链接中评论过的另一点是,您无法“升级”访问级别 . 如果你继承了某些东西,你可以更多地限制它,但不能相反 .
最后一点也会影响函数,元组和其他东西,如果函数使用私有类,那么将函数设置为internal或public是无效的,因为它们可能无法访问私有类 . 这会导致编译器警告,您需要将该函数重新声明为私有函数 .
For Swift 1-3:
不,这是不可能的 . 根本没有任何私有/受保护的方法和变量 .
一切都是公开的 .
Update 自Swift 4以来,可以在这个帖子中看到其他答案
您可以使用的一个选项是将实例创建包装到函数中,并在构造函数中提供适当的getter和setter:
现在处于测试阶段4,他们为Swift添加了访问修饰符 .
来自Xcode 6 beta 4 realese notes:
Swift 3 and 4 也为变量和方法的访问级别带来了很多变化 . Swift 3 and 4 现在有4个不同的访问级别,其中 open/public 访问是最高(限制性最小)访问级别, private 访问是最低(限制性最强)访问级别:
private 函数和成员只能在实体本身(struct,class,...)及其扩展的范围内访问(在Swift 3中,扩展也受到限制)
fileprivate 函数和成员只能在声明它们的源文件中访问 .
internal 函数和成员(默认情况下,如果未明确添加访问级别关键字)可以在定义它们的目标内的任何位置访问 . 这就是为什么TestTarget没有't have automatically access to all sources, they have to be marked as accessible in xCode'的文件检查器 .
可以从目标内的任何位置以及导入当前目标模块的任何其他上下文访问
open or public 函数和成员 .
Interesting:
您可以在类/结构的扩展中覆盖一些方法(例如,通常是辅助函数),并将整个扩展标记为“私有”,而不是将每个方法或成员标记为“私有” .
这可能是个好主意,以便获得更好的可维护代码 . 而且你可以轻松切换(例如,对于单元测试)通过仅改变一个单词来进行非私有 .
Apple documentation
直到swift 2.0只有三个访问级别[公共,内部,私有]但是在swift 3.0中苹果添加了两个新的访问级别,它们是[Open,fileType]所以现在在swift 3.0中有5个访问级别这里我要清除角色这两个访问级别1.打开:这与Public非常相似,但唯一的区别是Public可以访问子类并覆盖,而Open访问级别无法访问this image is taken from Medium website and this describe the difference between open and public access
现在到第二个新的访问级别2. filetype是私有的更大版本或者比内部更少的访问级别fileType可以访问[class,struct,enum]的扩展部分而private不能访问它只能访问的扩展部分代码词汇范围this image is taken from Medium website and this describe the difference between fileType and Private access level