through - properties swift
Captadores y establecedores de propiedades (9)
Actualización: Swift 4
En el setter y getter de clase inferior se aplica a sideLength
variable
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
}
}
Creando un objeto
var triangle = Triangle(sideLength: 3.9, name: "a triangle")
Adquiridor
print(triangle.perimeter) // invoking getter
Setter
triangle.perimeter = 9.9 // invoking setter
Con esta clase simple recibo la advertencia del compilador "Intentando modificar / acceder a ''x'' dentro de su propio setter / getter" y cuando lo uso así:
var p: point = Point()
p.x = 12
Obtengo un EXC_BAD_ACCESS. ¿Cómo puedo hacer esto sin ivars de respaldo explícitos?
class Point {
var x: Int {
set {
x = newValue * 2 //Error
}
get {
return x / 2 //Error
}
}
// ...
}
Estás definiendo recursivamente x
con x
. Como si alguien te preguntara ¿cuántos años tienes? Y respondes "Tengo el doble de mi edad". Que no tiene sentido
Debes decir que tengo el doble de la edad de John o cualquier otra variable que no seas tú mismo.
las variables calculadas siempre dependen de otra variable.
Intenta usar esto:
var x:Int!
var xTimesTwo:Int {
get {
return x * 2
}
set {
x = newValue / 2
}
}
Esta es básicamente la respuesta de Jack Wu, pero la diferencia es que en la respuesta de Jack Wu su variable x es var x: Int
, en el mío, mi variable x es así: var x: Int!
, así que todo lo que hice fue convertirlo en un tipo opcional.
Para anular setter
y getter
para variables rápidas, use el siguiente código
var temX : Int?
var x: Int?{
set(newX){
temX = newX
}
get{
return temX
}
}
Necesitamos mantener el valor de la variable en una variable temporal, ya que intentar acceder a la misma variable cuyo getter / setter se está anulando dará como resultado bucles infinitos.
Podemos invocar al colocador simplemente así
x = 10
Getter se invocará al disparar debajo de la línea de código dada
var newVar = x
Para profundizar en la respuesta de GoZoner:
Su verdadero problema aquí es que está llamando recursivamente a su 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
}
}
Al igual que el comentario del código sugiere más arriba, está llamando infinitamente al captador de la propiedad x, que continuará ejecutándose hasta que obtenga un código EXC_BAD_ACCESS (puede ver el rotador en la esquina inferior derecha del entorno de recreo de su Xcode).
Considere el ejemplo de la documentación de 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)
}
}
}
Observe cómo la propiedad calculada del centro nunca se modifica o se devuelve en la declaración de la variable.
Puede personalizar el valor establecido utilizando el observador de propiedades. Para hacer esto, use ''didSet'' en lugar de ''set''.
class point {
var x:Int {
didSet {
x = x * 2
}
}
...
En cuanto a getter ...
class point {
var doubleX:Int {
get {
return x / 2
}
}
...
Setters y Getters se aplican a las computed properties
; tales propiedades no tienen almacenamiento en la instancia; el valor del captador debe calcularse a partir de otras propiedades de instancia. En su caso, no hay x
para ser asignado.
Explícitamente: "¿Cómo puedo hacer esto sin ivars de respaldo explícitos". No puede: necesitará algo para hacer una copia de seguridad de la propiedad calculada. Prueba esto:
class Point {
private var _x: Int = 0 // _x -> backingX
var x: Int {
set { _x = 2 * newValue }
get { return _x / 2 }
}
}
Específicamente, en el REPL de Swift:
15> var pt = Point()
pt: Point = {
_x = 0
}
16> pt.x = 10
17> pt
$R3: Point = {
_x = 20
}
18> pt.x
$R4: Int = 10
Setters y getters en Swift se aplican a las propiedades / variables calculadas. Estas propiedades / variables no se almacenan realmente en la memoria, sino que se calculan en función del valor de las propiedades / variables almacenadas.
Consulte la documentación de Apple sobre el tema Swift Variable Declarations .
EDITAR : Dado que esta respuesta es obtener algunos votos favorables, me gustaría aclarar que setters / getters en Swift son bastante diferentes a ObjC. La propiedad se convierte en una propiedad calculada, lo que significa que no tiene una variable de respaldo como _x
como lo haría en ObjC. En el código de la solución a continuación, puede ver que xTimesTwo
no almacena nada, sino que simplemente calcula el resultado de x
.
Ver Documentos oficiales en propiedades calculadas .
La funcionalidad que desea también puede ser Property Observers .
Setters / getters son diferentes de lo que eran en Objective-C.
Lo que necesitas es:
var x:Int
var xTimesTwo:Int {
set {
x = newValue / 2
}
get {
return x * 2
}
}
Puede modificar otras propiedades dentro del setter / getters, que es para lo que están diseñadas.