【问题标题】:Can't use private property in extensions in another file不能在另一个文件的扩展中使用私有属性
【发布时间】:2017-02-06 11:00:46
【问题描述】:

我不能在扩展中使用私有属性。我的扩展名在另一个文件中。

如何在扩展中使用私有属性?

【问题讨论】:

  • 你试过用fileprivate代替private吗?
  • @thedjnivek My extension is in another file.
  • 你确定这在 Swift 2 中有效吗? Swift 2 中的“private”限制了对相同源文件的访问。
  • @MartinR 我不确定,因为在升级到 swift 3 后,我只是将主类和扩展名的文件分开
  • 所以你的问题与 Swift 2 vs Swift 3 无关,“在我升级到 swift 3.0 之后。我不能在扩展中使用私有属性” 具有误导性。

标签: ios swift swift3


【解决方案1】:

更新 从 Swift 4 开始,扩展可以访问在同一文件中声明的类型的私有属性。见Access Levels

如果一个属性被声明为private,则它的访问权限仅限于封闭声明,以及同一文件中该声明的扩展。

如果该属性被声明为fileprivate,则它只能在声明它的文件中使用(以及该文件中的任何东西)。

如果该属性被声明为internal(默认),则它只能在声明它的模块内使用(以及该文件中的任何东西)。

如果该属性被声明为publicopen,它可以被模块内的任何东西使用,也可以被导入声明它的模块的文件在模块外使用。

【讨论】:

  • 感谢您的回答,这对我来说真的很清楚。但我只需要清理我的代码。我只是想让它更清楚。这就是为什么我将扩展名从主文件中分离出来。是的,你完全理解。我不希望任何课程触及这个属性。在使其成为内部属性(我可以分离文件)和使其成为文件私有(将它们保留在主文件中)之间,您更喜欢哪一个
  • 不同的情况需要不同的用例。
  • 我的扩展用于在对象中设置样式。我决定暂时使用 fileprivate。我会将它们保留在主文件中。
【解决方案2】:

虽然@nhgrif 关于在 Swift 中缺少 protected 是多么痛苦的说法是正确的,但还是有办法解决的。

protocol 包装您的对象,并仅声明您希望公开的方法和属性。

举例

MyUtiltyClass.swift

protocol IMyUtiltyClass {
    func doSomething()
}

class MyUtiltyClass : IMyUtiltyClass {

    static let shared : IMyUtiltyClass = MyUtiltyClass()

    /*private*/
    func doSomethingPrivately() {

    }
}

MyUtiltyClass+DoSomething.swift

extension MyUtiltyClass {
    func doSomething() {
        self.doSomethingPrivately()
        print("doing something")
    }
}

然后您将对象视为接口类型,而不是直接作为类/结构类型。

MyViewController.swift

class MyViewController : UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        MyUtiltyClass.shared.doSomething()
        /*
         //⚠️ compiler error
         MyUtiltyClass.shared.doSomethingPrivately()
         */
    }
}

快乐编码?‍?

【讨论】:

  • 我觉得这个答案非常有用。特别是现在我正在创建一个 App Clip 并且我经常有一个共享文件(针对应用程序和剪辑),其中包含一个类和一个仅用于主应用程序的类的扩展,例如。谢谢!
  • 如果你有变量,这个技巧将不起作用。在此示例中,您可以看到编译器在尝试设置属性 protocol Protocol { var example: Bool { get set } } class Test: Protocol { var example: Bool = true static let shared: Protocol = Test() private init() { } } Test.shared.example Test.shared.example = false // Throws error "Cannot assign to property: 'shared' is a 'let' constant" 时出错
  • @Elena。如果您打算将协议用于参考变量。然后在协议定义中提及,如下protocol Protocol: AnyObject {protocol Protocol: class {
【解决方案3】:

在扩展中编写私有变量不是一个好习惯(即使我们可以)。它会引入意想不到的错误。

如果你想访问这个变量,你可以对那个变量使用 private(set) 使它对外部世界只读。

例如

private(set) var myPrivateVariable:Int

【讨论】:

  • 不确定这个答案是否未经投票,它解决了问题。
猜你喜欢
  • 2016-01-20
  • 2015-03-13
  • 1970-01-01
  • 2021-02-16
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多