Struct è un tipo valore (value type) nel linguaggio Swift, le cui istanze vengono copiate quando passate tra parti di codice. A differenza delle classi, le strutture non supportano l'ereditarietà, ma implementano protocolli, contengono proprietà e metodi e forniscono una gestione della memoria prevedibile senza ARC. Secondo la Swift Programming Language Guide, 2026, struct è un elemento costitutivo fondamentale di Swift — anche i tipi standard Int, String, Array e Dictionary sono implementati come strutture. Il linguaggio raccomanda le strutture come scelta prioritaria per la modellazione dei dati.
Punti chiave
Struct (struttura) è un tipo di dato composito in Swift che raggruppa proprietà e metodi correlati in un'unica entità. A differenza delle classi, le strutture sono value types: quando vengono passate a una funzione o assegnate a una nuova variabile, viene creata una copia indipendente della struttura, non un riferimento all'oggetto originale.
Swift utilizza strutture per tutti i tipi primitivi: Int, Double, String, Bool, Array, Dictionary e Set. Ciò significa che anche un Int di base si comporta come una struttura — viene creata una copia all'assegnazione. Lo sviluppatore può definire la propria struttura con qualsiasi insieme di proprietà e metodi.
Secondo Swift Evolution (SE-0143), la decisione di implementare i tipi standard come strutture è motivata da prestazioni e prevedibilità. I value types non creano cicli di riferimento, non richiedono il conteggio dei riferimenti ARC e garantiscono che la modifica di una copia non influisca sull'originale — questo è criticamente importante per l'immutabilità dei dati in scenari multithread.
La semantica dei value types è la differenza chiave tra struct e class. Quando si assegna una struttura a una nuova variabile o la si passa a una funzione, Swift crea una copia indipendente di tutti i dati. Qualsiasi modifica alla copia non influisce sull'originale, eliminando gli effetti collaterali tipici dei tipi riferimento.
// Esempio di semantica value type
struct Point {
var x: Double
var y: Double
}
var p1 = Point(x: 10, y: 20)
var p2 = p1 // p2 è una copia indipendente di p1
p2.x = 99 // Solo p2 cambia
print(p1.x) // 10 — p1 invariato
print(p2.x) // 99
Swift utilizza Copy-on-Write (COW) per ottimizzare la copia. Se più variabili fanno riferimento alla stessa struttura ma nessuna modifica i dati, non avviene alcuna copia effettiva. Swift condivide la memoria tra le variabili fino alla prima mutazione — quindi viene creata una copia reale. Ciò previene operazioni di allocazione eccessive e accelera il lavoro con le collezioni.
Per impostazione predefinita, i metodi di una struttura non possono modificarne le proprietà — Swift richiede la parola chiave esplicita mutating per i metodi che apportano modifiche. Questa restrizione protegge dalla mutazione accidentale e rende il codice prevedibile: se un metodo non è marcato come mutating, è garantito che non modifichi la struttura.
Quando si aggiunge la parola chiave mutating prima di un metodo, Swift acquisisce la capacità di scrivere nuovi valori nelle proprietà della struttura. In effetti, il metodo può persino sostituire completamente l'istanza della struttura con una nuova tramite self =. Questo meccanismo viene utilizzato, ad esempio, nei tipi Option e Result.
// Struct con metodo mutating
struct Counter {
private var value: Int = 0
// Metodo mutating — può modificare le proprietà
mutating func increment() {
value += 1
}
// Il metodo mutating può sostituire completamente self
mutating func reset() {
self = Counter()
}
// Metodo non mutating — sola lettura
func currentValue() -> Int {
return value
}
}
var counter = Counter()
counter.increment()
print(counter.currentValue()) // 1
counter.reset()
print(counter.currentValue()) // 0
Regole per mutating: la struttura deve essere dichiarata con var, non con let — una struttura costante non può chiamare un metodo mutating. Il compilatore lo verifica al momento della compilazione: tentare di chiamare un metodo mutating su una costante let causerà un errore di compilazione.
La scelta tra struct e class è una delle decisioni fondamentali in Swift. Entrambi i tipi possono contenere proprietà, metodi, inizializzatori e implementare protocolli, ma presentano differenze fondamentali nella semantica della memoria, nell'ereditarietà e nella gestione del ciclo di vita.
| Caratteristica | struct | class |
|---|---|---|
| Tipo | Value type (copiato) | Reference type (riferimento) |
| Ereditarietà | Non supportata | Supportata |
| ARC / conteggio dei riferimenti | Non richiesto | ARC richiesto |
| Deinizializzazione | Non supportata | Supporta deinit |
| Modifica proprietà nelle costanti | Solo tramite var | Possibile tramite let (il riferimento è costante) |
| Type casting | Non supportato | Supportato |
| Memorizzazione nelle collezioni | Memorizzato direttamente (valore) | Memorizzato come riferimento (puntatore) |
Le strutture sono preferibili quando i dati non richiedono ereditarietà, non devono avere identità condivisa (ad esempio, coordinate, dimensioni, configurazione) e vengono passati tra moduli. Le classi vengono scelte per i componenti dell'interfaccia utente (UIView, UIViewController), singleton e oggetti con identità condivisa.
Apple raccomanda di utilizzare struct come tipo predefinito per la modellazione dei dati in Swift. Le strutture sono adatte alla maggior parte degli scenari grazie alla semantica di copia prevedibile e all'assenza di overhead del conteggio dei riferimenti. Esaminiamo i casi tipici in cui struct è la scelta ottimale.
Se un'entità contiene dati senza necessità di ereditarietà (Product, User, Order, Point), utilizza struct. Il compilatore genera automaticamente un memberwise initializer — non è necessario scrivere init manualmente. Equatable e Hashable vengono anch'essi implementati automaticamente per le strutture le cui proprietà sono tutte conformi a questi protocolli.
Per configurazioni, impostazioni e flag che non cambiano dopo la creazione, struct è preferibile a class. Una struttura costante (let) garantisce l'immutabilità di tutti i campi annidati — in una class questo si applica solo al riferimento, non al contenuto dell'oggetto.
Le strutture sono sicure in ambienti multithread grazie alla semantica del valore. Ogni thread ottiene una copia indipendente dei dati e non influisce sugli altri thread. Le race condition tra thread sono impossibili per i value types, rendendo struct la scelta preferita per i modelli in SwiftUI (ObservableObject richiede class, ma @State utilizza struct).
// Esempio di utilizzo di struct per modello dati
struct User: Codable, Identifiable {
let id: UUID
var name: String
var email: String
var isPremium: Bool
// Proprietà calcolata — non mutating
var displayName: String {
isPremium ? "\(name) ⭐️" : name
}
}
// Inizializzatore memberwise automatico
let user = User(
id: UUID(),
name: "Alice",
email: "alice@example.com",
isPremium: true
)
// La copia è sicura per il multithreading
var userCopy = user
userCopy.isPremium = false
// user.isPremium rimane true
Utilizza class quando hai bisogno di ereditarietà (componenti UIKit/AppKit), identità condivisa (delegate, observer) o ciclo di vita controllato dell'oggetto (deinit). Per tutto il resto — utilizza struct.
Domande frequenti
Struct in Swift è un tipo valore che viene copiato quando passato tra parti di codice. Le strutture possono contenere proprietà, metodi, inizializzatori e implementare protocolli. I tipi di base di Swift (Int, String, Array) sono implementati come strutture.
Struct è un value type (copiato all'assegnazione), non supporta l'ereditarietà e non richiede ARC. Class è un reference type (passato per riferimento), supporta ereditarietà, deinizializzazione e conteggio dei riferimenti. Gli sviluppatori raccomandano struct come tipo predefinito.
Mutating è una parola chiave che indica che un metodo della struttura può modificarne le proprietà. Senza mutating, il compilatore vieta la modifica dei campi. I metodi mutating possono essere chiamati solo su variabili dichiarate con var, non con let.
Copy-on-Write (COW) è un'ottimizzazione di Swift per le strutture in cui la copia effettiva dei dati viene differita fino alla prima mutazione. Finchè tutte le variabili leggono solo la struttura, condividono una singola area di memoria. Ciò migliora le prestazioni quando si lavora con grandi collezioni.
Usa struct per modelli di dati senza ereditarietà, configurazioni, DTO e scenari multithread. Usa class per componenti UI UIKit/AppKit, singleton, entità con identità condivisa (delegate, observer) e oggetti che richiedono deinizializzazione.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche