可以从类外部访问私有 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 没有问题。 我的理解是,在班级 的边界之外,我不应该能够看到私人的任何东西,funcvar

我错过了什么吗?

【问题讨论】:

添加标签 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 访问 MyPrivateVarpriv 私有属性,因为 privMySecondClass 在同一个文件中(您的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的主要内容,如果未能解决你的问题,请参考以下文章

从类外部访问实例变量

读取外部类的隐藏私有字段

Python,从类外部访问小部件项

从 PHP 中的类外部调用私有方法和私有属性

类和对象的方法与属性---懒加载与私有事件---单例与私有化构造函数

Python面向对象-方法