Почему оператор присваивания '=' не работает в моем операторе if в моем наблюдателе свойства didSet?

struct Circle {
    // Properties

    var radius: Double {
        didSet {
            if oldValue < 0 {
                 radius = 0
            }
        }
    }
    var area:Double {
        get{
            return Double.pi * pow(radius, 2)
        }
    }
    var circumference: Double {
        get {
            return 2 * radius * Double.pi
        }
    }
    init() {
        radius = 0
    }
    init(radius r: Double) {
        radius = r
    }

}

// test circle

var testCircle = Circle()
print ("radius:", testCircle.radius, "area: ", testCircle.area, "circumference: ", testCircle.circumference)

var testCircle2 = Circle(radius: 2.5)
print("radius: ", testCircle2.radius, " area: ", testCircle2.area, "circumference: ", testCircle2.circumference)

var testCircle3 = Circle(radius: 20)
print("radius: ", testCircle3.radius, "area: ", testCircle3.area, "circumference: ", testCircle3.circumference)

var testCircle4 = Circle(radius: -4.5)
print("radius: ", testCircle4.radius, "area: ", testCircle4.area, "circumference: ", testCircle4.circumference)

2 ответа

didSet во время init, Вы можете обернуть задание в defer { ... } заявление о силе didSet быть названным.

Например:

init(radius r: Double) {
    defer { radius = r }
}

Если вы хотите, чтобы радиус по умолчанию был 0Я бы рекомендовал использовать значение параметра по умолчанию для radius вот так:

init(radius r: Double = 0) {
    defer { radius = r }
}

... таким образом вы избегаете использования двух методов init и по-прежнему инициализируете Circle как Circle() (radius = 0) и в качестве Circle(radius: 3) (radius = 3).

Помните, didSet вызывается после фактического изменения свойства oldValue будет содержать предыдущее значение.

Вы хотите проверить, является ли новое значение отрицательным.

Обновите код до:

var radius: Double {
    didSet {
        if radius < 0 {
            radius = 0
        }
    }
}

Вы хотите проверить, если radius (последнее значение) отрицательно.

Вы также должны обновить свой init метод:

init(radius r: Double) {
    radius = r >= 0 ? r : 0
}

Это потому что didSet а также willSet не вызываются во время инициализации. Так что ваши init Метод должен проверить параметр.

Как примечание может еще больше упростить ваш radius а также circumference свойства следующим образом:

var area:Double {
    return Double.pi * pow(radius, 2)
}

Свойство компьютера только для чтения не нуждается в get { },

Другие вопросы по тегам