Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Getters and Setters to modify values w/o Subclassing in Swift

Tags:

swift

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:

Checkpoints

I have two possible workarounds.

Option 1: Observe Value After Set

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.

Option 2: Subclass

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

Question

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?

like image 359
Logan Avatar asked Jun 05 '14 05:06

Logan


1 Answers

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).

like image 182
Analog File Avatar answered Oct 13 '22 06:10

Analog File