Reputation: 53112
Let's say I have a class, and when I set its property, I want it to append that property with a file type like .fileType
:
class File {
var fileName: String {
get {
return self.fileName
}
set {
self.fileName = fileName + ".fileType"
}
}
}
Which I try to use like this:
let newFile = File()
newFile.fileName = "My File"
Unfortunately, the variable never sets:
I have two possible workarounds.
class File {
var fileName: String = "" {
didSet {
self.fileName += ".fileType"
}
}
}
let file = File()
file.fileName = "SomeName" // SomeName.fileType
But with this, I must wait until the value is already set before I can modify it. For this particular example, it doesn't make too much difference; however, I'd like to be able to avoid this.
This solution is based on the example here. Search for 'speedLimitedCar'
class File {
var fileName = ""
}
class SubFile: File {
override var fileName: String {
get {
return super.fileName
}
set {
super.fileName = newValue + ".fileType"
}
}
}
let subfile = SubFile()
subfile.fileName = "Hello" // Hello.fileType
I could also just create a secondary property to store the value and access that in the fileName's getter/setter, but is there a way to avoid all that and modify a property directly within its getter / setter?
Upvotes: 5
Views: 13341
Reputation: 5316
If you use set
and get
then the property must be computed. There is no actual storage for it.
This code defines a var
to hold the data and a computed var
to handle the access. This is similar to what you had in Objective-C (except that in Objective-C you could "hide" the actual variable by making it private or, more recently, having it synthesized an never mentioned in the header).
class File {
// this stores the actual data, do not access it directly, consider it private
var theFileName: String = ""
// this is the real interface
var fileName: String {
get {
return self.theFileName
}
set(name) {
self.theFileName = name + ".fileType"
}
}
}
You can also write the set
like this:
set {
self.theFileName = newValue + ".fileType"
}
where newValue
is the default name if you omit the argument declaration for set
.
But what you probably want to do is what you already did (and rejected for unknown reasons):
var fileName: String = "" {
didSet {
self.fileName += ".fileType"
}
}
This is the correct way.
Note that "I must wait until the value is already set before I can modify it." is not true. It looks like that, but the compiler can very well optimize the code (and probably will).
Upvotes: 12