web-dev-qa-db-fra.com

Getters et setters de propriété

Avec cette classe simple, je reçois le compilateur warning  

Tentative de modification/d’accès à x dans son propre setter/getter

et quand je l'utilise comme ça:

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

Je reçois un EXC_BAD_ACCESS. Comment puis-je faire cela sans soutenir explicitement les ivars?

class Point {

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

Les Setters et Getters s’appliquent à computed properties; ces propriétés n'ont pas de stockage dans l'instance - la valeur du getter doit être calculée à partir d'autres propriétés d'instance. Dans votre cas, il n'y a pas de x à attribuer.

Explicitement: "Comment puis-je faire cela sans sauvegarder explicitement ivars". Vous ne pouvez pas - vous aurez besoin de quelque chose pour sauvegarder la propriété calculée. Essaye ça:

class Point {
  private var _x: Int = 0             // _x -> backingX
  var x: Int {
    set { _x = 2 * newValue }
    get { return _x / 2 }
  }
}

Plus précisément, dans le 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
208
GoZoner

Les Setters/Getters à Swift sont assez différents d’ObjC. La propriété devient une propriété calculée, ce qui signifie que non possède une variable de support telle que _x comme dans ObjC. 

Dans le code de solution ci-dessous, vous pouvez voir que xTimesTwo fait pas rien stocker, mais simplement calcule le résultat de x.

Voir Documents officiels sur les propriétés calculées .

La fonctionnalité souhaitée peut également être Observateurs de propriétés .

Ce dont vous avez besoin c'est:

var x:Int

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

Vous pouvez modifier d'autres propriétés dans le setter/getters, ce à quoi elles sont destinées.

97
Jack

Vous pouvez personnaliser la valeur définie à l'aide de la propriété observateur. Pour ce faire, utilisez 'didSet' au lieu de 'set'.

class Point {

var x:Int {
    didSet {
        x = x * 2
    }
}
...

Quant à getter ...

class Point {

var doubleX: Int {
    get {
        return x / 2
    }
}
...
89
cSquirrel

Pour élaborer sur la réponse de GoZoner:

Votre vrai problème ici est que vous appelez votre getter de manière récursive.

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
        }
    }

Comme le commentaire de code le suggère ci-dessus, vous appelez infiniment le getter de la propriété x, qui continuera à s'exécuter jusqu'à ce que vous obteniez un code EXC_BAD_ACCESS (vous pouvez voir le disque dans l'angle inférieur droit de l'environnement de jeu de votre Xcode).

Prenons l'exemple de la documentation 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)
        }
    }
}

Notez que la propriété center computed ne se modifie jamais ni ne se retourne dans la déclaration de la variable.

27
Abdullah Bakhsh

Afin de remplacer les variables setter et getter pour les variables Swift, utilisez le code ci-dessous 

var temX : Int? 
var x: Int?{

    set(newX){
       temX = newX
    }

    get{
        return temX
    }
}

Nous devons conserver la valeur de variable dans une variable temporaire, car essayer d'accéder à la même variable dont le getter/setter est surchargé entraînera des boucles infinies.

Nous pouvons invoquer le passeur simplement comme ceci 

x = 10

Getter sera invoqué au tir en dessous de la ligne de code 

var newVar = x
15
Sebin Roy

Vous êtes récursivement en définissant x avec x. Comme si quelqu'un te demandait quel âge as-tu? Et vous répondez "j'ai deux fois mon âge". Ce qui n'a pas de sens. 

Vous devez dire que j'ai deux fois l'âge de John ou toute autre variable mais vous-même.

les variables calculées dépendent toujours d'une autre variable.


La règle générale est never accéder à la propriété elle-même depuis entre le getter, c'est-à-dire get. Parce que cela déclencherait une autre get qui en déclencherait une autre. . . Ne l'imprimez même pas. Parce que l’impression nécessite aussi d’obtenir la valeur avant de pouvoir l’imprimer!

struct Person{
    var name: String{
        get{
            print(name) // DON'T do this!!!!
            return "as"
        }
        set{
        }
    }
}

let p1 = Person()

Comme cela donnerait l'avertissement suivant: 

Tenter d'accéder à 'nom' à partir de son propre getter.

L'erreur semble vague comme ceci:

 enter image description here

Au lieu de cela, vous pouvez utiliser didSet. Avec didSet, vous obtiendrez une valeur identique à celle qui avait été définie auparavant. Pour plus voir cette réponse .

8
Honey

Mise à jour: Swift 4

Dans la classe ci-dessous, le setter et le getter sont appliqués à la variable 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
        }
   }

Création d'objet

var triangle = Triangle(sideLength: 3.9, name: "a triangle")

Getter

print(triangle.perimeter) // invoking getter

Setter

triangle.perimeter = 9.9 // invoking setter
7
Saranjith

Essayez d'utiliser ceci: 

var x:Int!

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

Ceci est fondamentalement la réponse de Jack Wu, mais la différence est que, dans la réponse de Jack Wu, sa variable x est var x: Int, dans le mien, ma variable x est comme ceci: var x: Int!

6
Epic Defeater

Mise à jour pour Swift 5.1

À partir de Swift 5.1, vous pouvez maintenant obtenir votre variable sans utiliser le mot clé get. Par exemple:

var helloWorld: String {
"Hello World"
}
0
Atalay Aşa

Les setters et getters de Swift s’appliquent aux propriétés/variables calculées. Ces propriétés/variables ne sont pas réellement stockées en mémoire, mais calculées en fonction de la valeur des propriétés/variables stockées.

Consultez la documentation Swift d’Apple sur le sujet: Déclarations de variables Swift .

0
jefe2000

Voici une réponse théorique. Cela peut être trouvé ici

Une propriété {get set} ne peut pas être une propriété stockée constante. Ce doit être une propriété calculée et les deux méthodes get et set doivent être implémentées.

0
Talha Ahmad Khan