Cosa sono "get" e "set" in Swift?


101

Sto imparando Swift e sto leggendo The Swift Programming Languageda Apple, non ho un background in Objective C (solo PHP, JS e altri ma non Obj C)

A pagina 24-25 vedo questo codice:

//...Class definition stuff...

var perimeter: Double {
    get {
        return 3.0 * sideLength
    }
    set {
        sideLength = newValue / 3.0
    }
}

//...Class continues...

Questa parte NON è specificata nel libro e non riesco a capire a cosa servono.

Qualcuno può spiegarmi cosa sono get e set ?


2
Hai letto pg 21 su getter / setter. Inoltre, le prime 30 pagine circa sono un tour di Swift e non la documentazione completa.
vol7ron

Se hai fatto C ++ puoi correlare queste cose con le funzioni membro getter e setter della classe
CodingOnSteroid

Risposte:


38

Questo è effettivamente spiegato subito prima del codice:

Oltre alle proprietà semplici che vengono memorizzate, le proprietà possono avere un getter e un setter.

class EquilateralTriangle: NamedShape {
    ...

Quando un'altra classe vuole ottenere quella variabile perimetrale, lo fa:

let someVar = myTriangle.perimeter

... che chiama questo:

get{
    return 3.0 * self.sideLength
}

E quindi è essenzialmente come se il controller chiamante facesse questo:

let someVar = 3.0 * myTriangle.sideLength

Quando imposti la variabile da un altro oggetto, assomiglia a questo:

myTriangle.perimeter = 100

Che richiama il codice nel set{}blocco:

set {
    sideLength = newValue / 3.0
}

E quindi è come se la classe che sta impostando la variabile avesse fatto questo:

myTriangle.sideLength = 100/3.0

È davvero solo per comodità : puoi chiamarlo da altro codice senza dover dividere o moltiplicare per 3 tutto il tempo, perché è fatto subito prima di impostare la variabile e subito prima di ottenere la variabile.

In Swift, possiamo avere proprietà che vengono calcolate quando ottenute e possono fare qualcosa quando impostate. Potremmo farlo anche in Objective-C:

// .h
@property (nonatomic) double perimeter;

//.m

- (double)perimeter
{
    return self.sideLength * 3.0;
}
- (void)setPerimeter:(double)perimeter
{
    self.perimeter = perimeter; // In Swift, this is done automatically.
    self.sideLength = perimeter / 3.0;
}

108

Il recupero e l'impostazione delle variabili all'interno delle classi si riferisce al recupero ("acquisizione") o all'alterazione ("impostazione") del loro contenuto.

Considera una variabile membersdi una classe family. Naturalmente, questa variabile dovrebbe essere un numero intero, poiché una famiglia non può mai essere composta da due punti qualcosa di persone.

Quindi probabilmente andrai avanti definendo la membersvariabile in questo modo:

class family {
   var members:Int
}

Ciò, tuttavia, darà alle persone che utilizzano questa classe la possibilità di impostare il numero di membri della famiglia su qualcosa come 0 o 1. E poiché non esiste una famiglia di 1 o 0, questo è abbastanza sfortunato.

È qui che entrano in gioco i getter e i setter. In questo modo puoi decidere tu stesso come modificare le variabili e quali valori possono ricevere, oltre a decidere quale contenuto restituire.

Tornando alla nostra classe familiare, assicuriamoci che nessuno possa impostare il membersvalore su un valore inferiore a 2:

class family {
  var _members:Int = 2
  var members:Int {
   get {
     return _members
   }
   set (newVal) {
     if newVal >= 2 {
       _members = newVal
     } else {
       println('error: cannot have family with less than 2 members')
     }
   }
  }
}

Ora siamo in grado di accedere alla membersvariabile come prima, digitando instanceOfFamily.members, e grazie alla funzione setter, possiamo anche impostare il suo valore come prima, digitando, ad esempio: instanceOfFamily.members = 3. Ciò che è cambiato, tuttavia, è il fatto che non possiamo più impostare questa variabile su qualcosa di più piccolo di 2.

Notare l'introduzione della _membersvariabile, che è la variabile effettiva per memorizzare il valore che abbiamo impostato tramite la membersfunzione setter. L'originale membersè ora diventata una proprietà calcolata, il che significa che funge solo da interfaccia per gestire la nostra variabile effettiva.


members==> count, numberOfMembers; var members : Set<Person>??
GoZoner

1
set (newVal) { ... }, newVal è implicito, quindi set { _members = newVal }è anche corretto.
AndreasHassing

4
Nota che le variabili come _membersdovrebbero essere private, altrimenti il ​​comando instanceOfFamily._members=1verrebbe impostato instanceOfFamily.memberssu un valore inferiore a 2
Daniel

Sembra che il parametro predefinito sia denominato newValuein Swift 4 - docs.swift.org/swift-book/LanguageGuide/Properties.html#ID260
Nolan Amy

18

Una semplice domanda dovrebbe essere seguita da una risposta breve, semplice e chiara.

  • Quando otteniamo un valore della proprietà, spara la sua get{}parte.

  • Quando stiamo impostando un valore per la proprietà, attiva la sua set{}parte.

PS. Quando si imposta un valore alla proprietà, SWIFT crea automaticamente una costante denominata "newValue" = un valore che stiamo impostando. Dopo che una costante "newValue" diventa accessibile nella parte della proprietà set{}.

Esempio:

var A:Int = 0
var B:Int = 0

var C:Int {
get {return 1}
set {print("Recived new value", newValue, " and stored into 'B' ")
     B = newValue
     }
}

//When we are getting a value of C it fires get{} part of C property
A = C 
A            //Now A = 1

//When we are setting a value to C it fires set{} part of C property
C = 2
B            //Now B = 2

1
è obbligatorio assegnare un valore predefinito affinché il membro acceda dall'esterno della classe. Ho avuto questo problema come risolto quando assegno il valore predefinito per la classe UserBean: NSObject {var user_id: String? = nil} accedendovi in ​​questo modo consenti all'utente: UserBean = UserBean () user.user_id = "23232332"
Amr Angry

1

Dovresti guardare le proprietà calcolate

Nell'esempio di codice, perimeterè una proprietà non supportata da una variabile di classe, il suo valore viene invece calcolato utilizzando il getmetodo e memorizzato tramite il setmetodo, di solito indicato come getter e setter .

Quando usi quella proprietà in questo modo:

var cp = myClass.perimeter

stai invocando il codice contenuto nel getblocco di codice e quando lo usi in questo modo:

myClass.perimeter = 5.0

stai invocando il codice contenuto nel setblocco di codice, dove newValueviene automaticamente riempito con il valore fornito a destra dell'operatore di assegnazione.

Le proprietà calcolate possono essere readwrite se vengono specificati sia un getter che un setter, o readonly se è specificato solo il getter.


0

variabile dichiara e chiama in questo modo in una classe

class X {
    var x: Int = 3

}
var y = X()
print("value of x is: ", y.x)

//value of x is:  3

ora vuoi programmare in modo che il valore predefinito di x sia maggiore o uguale a 3. Ora prendi il caso ipotetico se x è minore di 3, il tuo programma fallirà. quindi, vuoi che le persone ne mettano 3 o più di 3. Swift è stato facile per te ed è importante capire questo modo in anticipo di datare il valore della variabile perché lo useranno ampiamente nello sviluppo iOS. Ora vediamo come verranno usati get e set qui.

class X {
    var _x: Int = 3
    var x: Int {
        get {
            return _x
        }
        set(newVal) {  //set always take 1 argument
            if newVal >= 3 {
             _x = newVal //updating _x with the input value by the user
            print("new value is: ", _x)
            }
            else {
                print("error must be greater than 3")
            }
        }
    }
}
let y = X()
y.x = 1
print(y.x) //error must be greater than 3
y.x = 8 // //new value is: 8

se hai ancora dubbi, ricorda che l'uso di get e set è per aggiornare qualsiasi variabile nel modo in cui vogliamo che venga aggiornata. get and set ti darà un controllo migliore per governare la tua logica. Strumento potente quindi non facilmente comprensibile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.