物业获取者和二传手
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了物业获取者和二传手相关的知识,希望对你有一定的参考价值。
有了这个简单的类,我得到编译器警告
试图在自己的setter / getter中修改/访问
x
当我像这样使用它时:
var p: point = Point()
p.x = 12
我得到一个EXC_BAD_ACCESS。如果没有明确支持ivars,我怎么能这样做呢?
class Point {
var x: Int {
set {
x = newValue * 2 //Error
}
get {
return x / 2 //Error
}
}
// ...
}
塞特斯和吸气者适用于computed properties
;这样的属性在实例中没有存储 - 来自getter的值应该从其他实例属性计算。在您的情况下,没有分配x
。
明确地说:“如果没有明确的支持ivars我怎么能这样做”。你不能 - 你需要一些东西来备份计算属性。试试这个:
class Point {
private var _x: Int = 0 // _x -> backingX
var x: Int {
set { _x = 2 * newValue }
get { return _x / 2 }
}
}
具体来说,在Swift REPL中:
15> var pt = Point()
pt: Point = {
_x = 0
}
16> pt.x = 10
17> pt
$R3: Point = {
_x = 20
}
18> pt.x
$R4: Int = 10
这是一个理论上的答案。这可以找到here
{get set}属性不能是常量存储属性。它应该是一个计算属性,并且应该实现get和set。
Swift中的Setter / getters与ObjC完全不同。该属性成为计算属性,这意味着它没有像在ObjC中那样的_x
等支持变量。
在下面的解决方案代码中,您可以看到xTimesTwo
不存储任何内容,而只是计算x
的结果。
见Official docs on computed properties。
您想要的功能也可能是Property Observers。
你需要的是:
var x:Int
var xTimesTwo:Int {
set {
x = newValue / 2
}
get {
return x * 2
}
}
您可以修改setter / getters中的其他属性,这就是它们的用途。
您可以使用属性观察者自定义设置值。要做到这一点,请使用'didSet'而不是'set'。
class Point {
var x:Int {
didSet {
x = x * 2
}
}
...
至于吸气...
class Point {
var doubleX: Int {
get {
return x / 2
}
}
...
详细说明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 documentation的例子:
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)
}
}
}
注意中心计算属性永远不会在变量的声明中修改或返回自身。
为了替换快速变量的setter
和getter
,请使用下面给出的代码
var temX : Int?
var x: Int?{
set(newX){
temX = newX
}
get{
return temX
}
}
我们需要将变量的值保存在临时变量中,因为尝试访问其getter / setter被覆盖的同一变量将导致无限循环。
我们可以像这样调用setter
x = 10
在给定的代码行下面将触发Getter
var newVar = x
你用x
递归地定义x
。好像有人问你你多大了?你回答“我是我的两倍”。这没有意义。
你必须说我是约翰的年龄或任何其他变量,但你自己。
计算变量总是依赖于另一个变量。
拇指规则永远不会从吸气剂即get
中获取属性本身。因为这会引发另一个触发另一个的get
。 。 。甚至不打印。因为打印还需要在打印之前“获取”该值!
struct Person{
var name: String{
get{
print(name) // DON'T do this!!!!
return "as"
}
set{
}
}
}
let p1 = Person()
因为这会发出以下警告:
试图从它自己的getter中访问'name'。
该错误看起来像这样模糊:
作为替代方案,您可能想要使用didSet
。使用didSet
,您将获得之前设置的值,并且设置为。有关更多信息,请参阅this answer。
更新:Swift 4
在下面的类中,setter和getter应用于变量sideLength
class Triangle: {
var sideLength: Double = 0.0
init(sideLength: Double, name: String) { //initializer method
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 3
}
var perimeter: Double {
get { // getter
return 3.0 * sideLength
}
set { //setter
sideLength = newValue / 4.0
}
}
创建对象
var triangle = Triangle(sideLength: 3.9, name: "a triangle")
消气
print(triangle.perimeter) // invoking getter
二传手
triangle.perimeter = 9.9 // invoking setter
试试这个:
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!
,所以我所做的只是让它成为一个可选类型。
Swift中的setter和getter适用于计算属性/变量。这些属性/变量实际上并不存储在内存中,而是基于存储的属性/变量的值进行计算。
请参阅Apple关于此主题的Swift文档:Swift Variable Declarations。
以上是关于物业获取者和二传手的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 http 请求在 Instagram 中获取关注者和关注列表