Быстрое программирование: getter/setter в сохраненной собственности
Как перезаписать установщик хранимого свойства в Swift?
В Obj-C я могу перезаписать свой сеттер, но Swift, похоже, не очень рад, что getter/setters используются для сохраненного свойства.
Скажем, у меня есть класс Card
со свойством rank
. Я не хочу, чтобы клиент дал ему какое-либо недопустимое значение, поэтому в objective-C я могу перезаписать setRank
, чтобы он выполнял дополнительную проверку. Но willSet
в Swift, похоже, не помогает, потому что newValue
является константой, и нет смысла назначать rank
, потому что setter будет вызываться в цикле.
Ответы
Ответ 1
Ok. Чтение документации на яблоки Swift я нашел this:
Если вы присваиваете значение свойству в своем собственном наблюдателе, новое значение, которое вы назначили, заменит тот, который был только что установлен.
Итак, все, что вам нужно сделать, это следующее:
var rank: Int = 0 {
didSet {
// Say 1000 is not good for you and 999 is the maximum you want to be stored there
if rank >= 1000 {
rank = 999
}
}
}
Ответ 2
Вы не можете переопределить get
/set
для сохраненного свойства, но вы можете использовать наблюдатели свойств willSet
/didSet
:
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
println("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
println("Added \(totalSteps - oldValue) steps")
}
}
}
Имена параметров по умолчанию newValue
для willSet
и oldValue
для didSet
, или вы можете назвать их самостоятельно, как в willSet(newTotalSteps)
.
Ответ 3
get и set предназначены для вычисляемых свойств (у них нет резервного хранилища).
(На мой взгляд, ключевое слово "var" здесь запутывает)
- willSet и didSet вызывают для переменной экземпляра (Use doSet для переопределения любых изменений)
- set и get являются чисто рассчитанными свойствами
Ответ 4
Если вы не хотите использовать didSet, у которого есть проблема, что значение свойства временно неверно, вы должны обернуть вычисляемое свойство вокруг него.
private var _foo:Int = 0
var foo:Int {
get {
return _foo
}
set {
if(newValue > 999) {
_foo = 999
} else {
_foo = newValue
}
}
}
Или:
private var _foo:Int = 0
var foo:Int {
get {
return _foo
}
set {
guard newValue <= 999 else {
_foo = 999
return
}
_foo = newValue
}
}
Ответ 5
Упрощенный пример:
class Shape {
var sideLength: Double {
get {
return self.sideLength
}
set {
// Implement the setter here.
self.sideLength = newValue
}
}
}
Полный пример
Проверьте perimeter
в этом примере.
Отрывок из: Apple Inc. "Быстрый язык программирования". интерактивные книги. https://itun.es/us/jEUH0.l
class EquilateralTriangle: NamedShape {
var sideLength: Double = 0.0
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 3
}
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
override func simpleDescription() -> String {
return "An equilateral triagle with sides of length \(sideLength)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength"