【问题标题】:Private Var Inside a Class in SwiftSwift 类中的私有变量
【发布时间】:2016-06-26 17:10:09
【问题描述】:

我希望在 Swift 中的类中声明一个私有变量,并使用公共(实际上是内部)方法访问它。下面的代码对吗?

class someClass {

  // Using underscore here to distinguish variable and method
  private var _privateArray: [String]
  ...
  func privateArray() {
    return _privateArray
  }

  func setPrivateArray(someArray: [String]) {
    _privateArray = someArray
  }
}

我想使用上面的原因是因为我想在任何子类中使用数组,但名称对子类有意义。

class someSubclass: someClass {

  var arrayWithMeaningfulName: [String]

  init() {
    arrayWithMeaningfulName = super.privateArray()
    ...
  }
}

不确定以上是否是实现我想要的最佳方式。感谢您的反馈。

顺便说一句,我确实尝试如下声明私有变量,但编译器抱怨:

class someClass {

  private var _privateArray: [String] {
    get {
      ...
    }

    set {
    ...
  }
  ...

【问题讨论】:

  • 是什么让您认为它可能不是“正确的”?
  • 公共访问器对私有变量有什么好处/用途(严肃的问题)?
  • "The reason I want to use the above is because I want to use the array in any subclasses, but with a name which is meaningful to the subclass." 这对我来说没有多大意义。当然,我完全赞成命名良好的变量,但我认为我需要一个更具体的例子来说明你在这里试图完成的事情,因为它没有多大意义。
  • Scott Hunter 我认为 Thomas A 已经回答了你的问题;我应该使用计算属性而不是这两种方法。
  • @Koen 你也需要封装你的数据,即使你设置它......所以你可以过滤你不想要的值,即:if myValue < 0, then don't set it and return an error

标签: swift accessor


【解决方案1】:

以下似乎有效。

class SomeClass {

    // Using underscore here for consistency with my original post
    private var _privateArray: [String] = ["a", "b", "c"]

    func reverse() {
        _privateArray = _privateArray.reverse()
    }
}

class SomeSubclass: SomeClass {

    // The array in this subclass is a computed property
    var arrayWithMeaningfulName: [String] {
        get {
            return super._privateArray
        }

        set(newArray) {
            super._privateArray = newArray
        }
    }
}

重要提示: SomeSubclass 必须在定义 SomeClass 的同一源文件中定义,才能访问私有成员 _privateArray。例如,如果 SomeClass 在文件 SomeClass.swift 中定义,那么 SomeSubclass 也必须在文件 SomeClass.swift 中定义。如果不是,编译器会报错“'SomeClass' 类型的值没有成员变量'_privateArray'。”

“反向”方法是为了证明可以在父类中定义公共代码以避免重复,即使每个子类的成员变量都有不同的(更有意义的)名称。

【讨论】:

    【解决方案2】:

    请注意,Swift 书有以下内容:

    您可以为 setter 赋予低于其对应权限的访问级别 getter,以限制该变量、属性的读写范围, 或下标。您可以通过编写 private(set) 来分配较低的访问级别 或 internal(set) 在 var 或 subscript 介绍者之前。

    所以,在你的例子中,你可以简单地拥有

    public class SomeClass {
        public private(set) var privateArray: [String] = []
        public func setPrivateArray(array: [String]) {
           // do some checking, possibly
           self.privateArray = array
        }
    }
    

    您的代码中存在各种语法错误 - 您在公共函数中缺少 func,并注意您不能赋予属性或函数比其父对象更高的访问级别,因此您必须声明该类本身为public

    【讨论】:

    • Grimxn,感谢您指出我狡猾的代码中的错误,希望我已经全部改正。当我说“公共”时,我的意思是默认的,内部的。
    【解决方案3】:

    如果你想声明一个private 成员,你所要做的就是:

    class myClass {
    
        private var _myVar = [String]() // For example
    
        var myVar: [String] {
    
            // Getter
            get {
                return self._myVar
            }
    
            // Setter
            set(newValue) {
    
                self._myVar = newValue
            }
        }
    }
    

    【讨论】:

    • 噢!所以只是为了确认, myVar 是一个计算属性?我一定是太累了……谢谢。
    • myVar 是您要处理的班级成员...所以是的
    • 虽然您的代码是正确的,但它并不能提供我想要的,因为我不希望公开访问 _myVar,即使是通过 myVar。
    猜你喜欢
    • 2020-06-12
    • 2015-11-14
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    • 2014-05-23
    • 2015-09-25
    • 1970-01-01
    • 2011-11-05
    相关资源
    最近更新 更多