我正在研究我们应该为我们的属性使用Get和Set的原因。
我注意到它有三个主要原因
下面的代码是一个如何在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
}
}
所以我很想知道每种实施的优点和缺点是什么。
提前致谢
答案 0 :(得分:4)
您的问题归结为编译时间与运行时错误。解决你的3个问题:
willCheck
是您唯一的选择fatalError
中抛出didSet
,则会出现运行时错误,并且您的应用程序将崩溃。您的代码第一个示例在定义支持变量时过于冗长 - 您不需要这样做。为了说明这些要点:
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中的private
的说明:如果您在Swift 2游乐场中尝试此操作,您会发现t.greeting = "Goodbye world"
工作正常。这是因为Swift 2有一个奇怪的访问级别说明符:private
表示“只能在当前文件中访问”。将类定义和示例代码分成不同的文件,Xcode会抱怨。在Swift 3中,它被更改为fileprivate
,它更清晰,并保存private
关键字,以便更类似于Java和.NET