通过这个简单的类,我得到了编译器警告

试图在自己的setter/getter中修改/访问x

当我这样使用它时:

var p: point = Point()
p.x = 12

我得到一个EXC_BAD_ACCESS。我怎么能做到这一点没有显式支持变量?

class Point {

    var x: Int {
        set {
            x = newValue * 2 //Error
        }
        get {
            return x / 2 //Error
        }
    }
    // ...
}

当前回答

详细解释一下GoZoner的回答:

这里真正的问题是递归地调用getter。

var x:Int
    {
        set
        {
            x = newValue * 2 // This isn't a problem
        }
        get {
            return x / 2 // Here is your real issue, you are recursively calling 
                         // your x property's getter
        }
    }

就像上面的代码注释建议的那样,你无限地调用x属性的getter,它将继续执行,直到你得到一个EXC_BAD_ACCESS代码(你可以在你的Xcode的游乐场环境的右下角看到旋转器)。

请看Swift文档中的例子:

struct Point {
    var x = 0.0, y = 0.0
}
struct Size {
    var width = 0.0, height = 0.0
}
struct AlternativeRect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}

注意,center computed属性在变量的声明中从不修改或返回自身。

其他回答

这里有一个理论上的答案。可以在这里找到

{get set}属性不能是常量存储属性。它应该是一个计算属性,get和set都应该被实现。

Swift中的setter和getter适用于计算的属性/变量。这些属性/变量实际上并不存储在内存中,而是根据存储的属性/变量的值计算出来的。

请参阅Apple的Swift文档:Swift变量声明。

Swift中的setter /getter与ObjC有很大不同。属性变成一个计算属性,这意味着它不像在ObjC中那样有一个支持变量,比如_x。

在下面的解决方案代码中,您可以看到xTimesTwo不存储任何东西,而是简单地计算x的结果。

请参阅有关计算属性的官方文档。

您想要的功能也可能是Property observer。

你需要的是:

var x: Int

var xTimesTwo: Int {
    set {
       x = newValue / 2
    }
    get {
        return x * 2
    }
}

您可以在setter/getter中修改其他属性,这就是它们的意义所在。

试试这个:

var x:Int!

var xTimesTwo:Int {
    get {
        return x * 2
    }
    set {
        x = newValue / 2
    }
}

这基本上是Jack Wu的答案,但不同的是,在Jack Wu的答案中,他的x变量是var x: Int,在我的答案中,我的x变量是这样的:var x: Int!,所以我所做的只是使它成为一个可选类型。

我不知道这是不是一个好的练习,但是你可以这样做:

class test_ancestor {
    var prop: Int = 0
}


class test: test_ancestor {
    override var prop: Int {
        get {
            return super.prop // reaching ancestor prop
        }
        set {
            super.prop = newValue * 2
        }
    }
}

var test_instance = test()
test_instance.prop = 10

print(test_instance.prop) // 20

阅读更多