为什么' ='赋值运算符在我的didSet属性observer中的if语句中不起作用?

时间:2017-09-08 21:50:54

标签: swift property-observer

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 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

请记住,在实际更改属性后调用didSetoldValue将包含之前的值。

您想检查新值是否为负值。

将代码更新为:

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

您想检查radius(最新值)是否为负数。

您还需要更新init方法:

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

这是因为在初始化期间未调用didSetwillSet。因此,您的init方法需要验证参数。

附注可以进一步简化您的radiuscircumference属性,如下所示:

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

只读计算机属性不需要get { }