可以从类外部访问私有 var
Posted
技术标签:
【中文标题】可以从类外部访问私有 var【英文标题】:Private var is accessible from outside the class 【发布时间】:2014-09-28 17:15:12 【问题描述】:这是在 Playground 中完成的,只是为了简化。
class MyPrivateVar
private var priv: String?
var myInstance = MyPrivateVar()
myInstance.priv = "Something"
没有编译器警告。事实上,自动完成显示priv
没有问题。
我的理解是,在班级 的边界之外,我不应该能够看到私人的任何东西,func
或 var
。
我错过了什么吗?
【问题讨论】:
添加标签 swift2 因为这在 swift3 中不再适用 【参考方案1】:Swift 中的访问修饰符的实现方式与其他语言不同。共有三个级别:
private
:只能在该特定文件中访问
internal
:只能在模块(项目)内访问
public
:可从任何地方访问
除非另有标记,否则您编写的所有内容默认为internal
。
在 beta 4 中引入这些功能时的Swift blog had a post about access control,以及Apple's documentation has a chapter。
【讨论】:
"私有访问将实体的使用限制在其自己的定义源文件中。使用私有访问来隐藏特定功能的实现细节。"。我猜当他们说“文件”时,他们实际上是认真的。将private
范围限制为不属于自己的类,而是限制在它所在的物理文件中并没有太大意义。我想在同一个文件中包含类不只是方便,它有功能意义。可能与“私人”标头未复制到外部有关。
答案中链接的博客文章介绍了他们使用这种非标准系统的一些原因,他们有another post on why they didn't include "protected" 进行了更详细的说明。
在 Swift 3 中,这将改变,因此 private
将声明限制在当前范围内,fileprivate
(新的访问修饰符)将执行 private
在 Swift 3 之前所做的事情。@987654324 @ 对 Swift 3 中的访问修饰符有很好的总结。【参考方案2】:
注意:此答案适用于 Swift 2
Swift 编程语言指出:
Swift 为您的实体中的实体提供了三种不同的访问级别 代码。这些访问级别是相对于源文件的 实体已定义,并且也相对于源文件的模块 属于。
如果你不想用 Swift 测试private
的访问级别,下面的步骤可能会对你有所帮助。
1/ 创建一个新的 Xcode 项目。
2/ 创建一个文件MyPrivateVar.swift,并在其中添加以下代码:
class MyPrivateVar
private var priv: String? = nil
3/ 创建第二个文件MySecondClass.swift,并在其中添加以下代码:
class MySecondClass
init()
var myPrivateVar = MyPrivateVar()
myPrivateVar.priv = "some string"
Xcode 会立即给你一个 Swift 编译器错误信息:
“MyPrivateVar”没有名为“priv”的成员
4/ 现在,从您的项目中删除之前的两个文件并创建一个文件 TwoClassesInAFile.swift,其中包含以下代码:
class MyPrivateVar
private var priv : String? = nil
class MySecondClass
init()
var myPrivateVar = MyPrivateVar()
myPrivateVar.priv = "some string"
这一次,您不会收到 Swift 编译器错误消息,并且您将能够从 MySecondClass
访问 MyPrivateVar
的 priv
私有属性,因为 priv
和 MySecondClass
在同一个文件中(您的TwoClassesInAFile.swift 文件)。
此外,访问级别也适用于全局变量。例如,如果以下代码是同一个 ViewController.swift 文件的一部分,Xcode 不会给出任何编译器错误:
import UIKit
private var globalPrivate : String? = nil
class ViewController: UIViewController
override func viewDidLoad()
super.viewDidLoad()
globalPrivate = "some string"
println(globalPrivate)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
但是,如果您在 ViewController.swift 之外定义 globalPrivate
,Xcode 将生成错误消息:
使用未解析的标识符“globalPrivate”
【讨论】:
使用 Playground 只是为了仔细检查。原始问题发生在项目中的视图控制器文件上。我注意到我正在使用 Playground 来简化问题。 在 swift 3 和 xcode 8 中第 4 点是错误的。 class AccessModifiersClass private var privV : String?内部变量 inteV:字符串?公共变量 publV:字符串? var defV : 字符串? class CheckPoint init() globalPrivate = "some string" let lVar = AccessModifiersClass() lVar.priv = "Public" lVar.inteV = "Internal" lVar.publV = "Public" lVar.defV = "default"以上是关于可以从类外部访问私有 var的主要内容,如果未能解决你的问题,请参考以下文章