我正在研究我们应该为我们的属性使用Get和Set的原因.
我注意到了3个主要原因
>如果你想在实际设置之前做/检查一些事情
属性
>如果您想拥有一个只能从中获取的属性
(可能出于安全考虑,我猜?),或给它不同的访问权限
水平.
>在暴露a时隐藏属性的内部表示
使用替代表示的财产. (对我来说没有
因为我可以使用在错误的地方访问它,所以很有意义
无论如何都要设置功能)
下面的代码是一个如何在Swift中实现Get和Set属性的示例,利用我提到的3点:
class Test { private var _testSet:String! private var _testGetOnly:String var testSet:String{ get{ return _testSet } set{ _testSet = newValue + "you forgot this string" } } var testGetOnly:String!{ get{ return _testGetOnly } } init(testSet:String,testGetOnly:String) { _testSet = testSet _testGetOnly = testGetOnly } }
但是下面的另一个例子也利用了提到的那些点,而不是使用另一个计算属性来返回私有属性值我只使用了willSet和didSet观察者
class Test { var testGet:String { willSet{ fatalError("Operation not allowed") } } var testWillSet:String!{ didSet{ self.testWillSet = self.testWillSet + "you forgot this string" } } init(testGet:String,testWillSet:String) { self.testGet = testGet self.testWillSet = testWillSet } }
所以我很想知道每个实现的优点和缺点是什么.
提前致谢
您的问题归结为编译时间与运行时错误.解决您的3个问题:
原文链接:https://www.f2er.com/swift/319406.html>是的,willCheck是您唯一的选择
>只读属性分为两种类型:(a)其值来自其他属性的那些,例如,它们的总和; (b)您希望能够自行更改但不能由用户更改的内容.第一种类型真的没有二传;第二种类型有一个公共吸气剂和一个私人二传手.编译器可以帮助您检查它,程序将无法编译.如果在didSet中抛出fatalError,则会出现运行时错误,应用程序将崩溃.
>可能存在您不希望用户自由处理的状态对象,是的,您可以完全隐藏用户的状态.
您的代码第一个示例在定义支持变量时过于冗长 – 您不需要这样做.为了说明这些要点:
class Test { // 1. Validate the new value var mustBeginWithA: String = "A word" { willSet { if !newValue.hasPrefix("A") { fatalError("This property must begin with the letter A") } } } // 2. A readonly property var x: Int = 1 var y: Int = 2 var total: Int { get { return x + y } } private(set) var greeting: String = "Hello world" func changeGreeting() { self.greeting = "Goodbye world" // Even for private property,you may still // want to set it,just not allowing the user // to do so } // 3. Hide implementation detail private var person = ["firstName": "","lastName": ""] var firstName: String { get { return person["firstName"]! } set { person["firstName"] = newValue } } var lastName: String { get { return person["lastName"]! } set { person["lastName"] = newValue } } var fullName: String { get { return self.firstName + " " + self.lastName } set { let components = newValue.componentsSeparatedByString(" ") self.firstName = components[0] self.lastName = components[1] } } }
用法:
let t = Test() t.mustBeginWithA = "Bee" // runtime error t.total = 30 // Won't compile t.greeting = "Goodbye world" // Won't compile. The compiler does the check for you // instead of a crash at run time t.changeGreeting() // OK,greeting now changed to "Goodbye world" t.firstName = "John" // Users have no idea that they are actually changing t.lastName = "Smith" // a key in the dictionary and there's no way for them // to access that dictionary t.fullName = "Bart Simpsons" // You do not want the user to change the full name // without making a corresponding change in the // firstName and lastName. With a custome setter,you // can update both firstName and lastName to maintain // consistency
关于Swift 2与Swift 3中的私密性的说明:如果你在Swift 2游乐场试试这个,你会发现t.greeting =“Goodbye world”的效果很好.这是因为Swift 2有一个奇怪的访问级别说明符:private表示“只能在当前文件中访问”.将类定义和示例代码分成不同的文件,Xcode会抱怨.在Swift 3中,它被更改为fileprivate,它更清晰,并保存private关键字,以便更类似于Java和.NET