Getter è un metodo che viene chiamato ogni volta che si accede (lettura valore da) a una proprietà (dichiarata con @property
). Qualunque cosa questo metodo restituisce è considerata valore della proprietà:
@property int someNumber;
...
- (int)someNumber {
return 42;
}
...
NSLog("value = %d", anObject.someNumber); // prints "value = 42"
Setter è un metodo che viene richiamato ogni volta che viene modificato il valore della proprietà.
- (void)setSomeNumber: (int)newValue { // By naming convention, setter for `someValue` should
// be called `setSomeValue`. This is important!
NSLog("someValue has been assigned a new value: %d", newValue);
}
...
anObject.someNumber = 19; // prints "someValue has been assigned a new value: 19"
Di solito non ha molto senso per tornare solo lo stesso valore di getter e stampare nuovo valore nel setter. Per memorizzare in realtà qualcosa si deve dichiarare una variabile di istanza (Ivar) nella classe:
@interface SomeClass : NSObject {
int _someNumber;
}
e rendere di accesso (il nome collettivo di getter e setter) per memorizzare/recuperare il suo valore:
- (int)someNumber {
return _someNumber;
}
- (void)setSomeNumber:(int)newValue {
_someNumber = newValue;
}
...
SomeClass *anObject = [[SomeClass alloc]init];
anObject.someNumber = 15;
NSLog(@"It's %d", anObject.someNumber); // prints "It's 15"
Okay, ora che la proprietà si comporta proprio come la variabile al solito. Qual è il punto nello scrivere tutto quel codice?
Innanzitutto, da ora in poi è possibile aggiungere un codice aggiuntivo agli accessor, che verrà eseguito ogni volta che si accede o si modifica la proprietà. Ci sono molte ragioni per farlo, per esempio potrei voler fare qualche tipo di calcoli nascosti, o aggiornare lo stato del mio oggetto, la cache ecc.
In secondo luogo, ci sono meccanismi interessanti chiamati Key-Value Coding (KVC) e Key-Value Observing (KVO) in cacao. Dipendono dalle proprietà. Puoi leggere informazioni su di loro nella Developer Library: KVC Programming Guide e KVO Programming Guide. Questi sono argomenti avanzati però.
Infine, nell'obiettivo C non esiste un'assegnazione statica per gli oggetti. Tutti gli oggetti sono allocati dinamicamente (reason). Se si desidera mantenere i puntatori oggetto nelle variabili di istanza (anziché nelle proprietà), sarà necessario eseguire manualmente tutta la gestione della memoria ogni volta che si assegna un nuovo valore a ivar (non vero quando è attivo). Usando le proprietà potresti mettere un po 'di codice di gestione della memoria nelle funzioni di accesso e semplificarti la vita.
Non credo che questa spiegazione abbia molto senso per qualcuno che non ha familiarità con la gestione della memoria dell'obiettivo C, quindi, o leggere alcuni documenti/tutorial reali su di esso, o semplicemente utilizzare le proprietà (invece delle variabili di istanza) fino a quando impari tutti i dettagli in un modo o nell'altro. Personalmente, non mi piace la seconda opzione, ma dipende da te.
È possibile utilizzare @synthesize
per consentire al compilatore di generare automaticamente accessorie di base e variabili di istanza sottostanti. Invece del codice di cui sopra (e -(int)someNumber
-(void)setSomeNumber:
) si può solo scrivere
@synthesize someNumber = _someNumber; // = _someNumbers tells compiler
// to name the instance variable `_someNumber`.
// You could replace it with = `_somethingElse`, of
// course, but that's an ill idea.
Questa singola linea genera int _someNumber
variabile, someNumber
getter e setter setSomeNumber
per voi. Se vuoi che gli accessor facciano qualcosa di più complesso del semplice salvataggio/recupero del valore da qualche variabile di istanza, dovrai scriverli tu stesso.
Spero che tutto ciò abbia un senso.