Le proprietà statiche e di classe sono proprietà appartenenti al tipo, non all'istanza. Storicamente sono state introdotte per risolvere il problema della memorizzazione di informazioni comuni a tutte le istanze (ad esempio, contatori, configurazioni, fabbriche). In Swift, static può essere utilizzato in tutti i tipi (class, struct, enum), mentre class solo all'interno delle classi e solo per proprietà calcolate, consentendo la possibilità di essere sovrascritte nei sottotipi.
Problema: un uso improprio delle proprietà statiche può portare a condizioni di gara e errori di accesso da thread diversi. È anche facile confondere static e class e scegliere il meccanismo sbagliato per l'override nei sottotipi.
Soluzione:
Esempio di codice:
class Counter { static var count = 0 static let queue = DispatchQueue(label: "counter.queue") static func increment() { queue.sync { count += 1 } } class var typeDescription: String { return "Generic Counter" } } class NamedCounter: Counter { override class var typeDescription: String { return "Named Counter" } }
Caratteristiche chiave:
Domanda 1: È possibile dichiarare una proprietà static let come proprietà calcolata (computed) con get?
Sì, la proprietà static può essere sia stored che computed. Per le proprietà let, di solito è una costante, tuttavia static var può essere benissimo calcolata:
struct Math { static var pi: Double { return 3.1415926 } }
Domanda 2: Le static var sono thread-safe per impostazione predefinita?
No, se static var viene modificata da thread diversi, possono verificarsi condizioni di gara. read/write devono essere sincronizzati manualmente.
Domanda 3: È possibile utilizzare class var per proprietà stored?
No, class var deve sempre essere una proprietà calcolata (property with get/optional set), le proprietà stored sono consentite solo per static.
In un'app, il contatore di accesso dell'utente era memorizzato in static var e incrementato da thread diversi senza sincronizzazione.
Vantaggi:
Svantaggi:
Per un oggetto di configurazione globale è stato utilizzato static let e l'accesso a esso era solo in lettura o utilizzando DispatchQueue per la scrittura.
Vantaggi:
Svantaggi: