2014-09-25 22 views
18

Mentre giocavo un po 'con Swift, ho provato a scrivere una proprietà inizializzata readonly e pigra. Ho scritto rapidamente quella riga di codice solo per sapere che non è permesso.Lazy proprietà readonly in swift

// no valid Swift code. 
lazy let foo : Int = { return 42 }() 

si deve dichiarare proprietà pigri come var. Il libro veloce afferma chiaramente che lascia con il pigro non è possibile per una buona ragione:

“Si deve sempre dichiarare una proprietà pigro come una variabile (con la parola chiave var), perché il suo valore iniziale potrebbe non essere recuperate fino a dopo l'inizializzazione dell'istanza completa. proprietà costanti devono sempre avere un valore prima inizializzazione viene completata, e quindi non può essere dichiarato come pigrizia.”

Supponendo desidero avere una proprietà artificiale sola lettura in rapida. Qual è il modo migliore per archiviarlo?

risposta

33

Se in sola lettura e private sono sinonimi di voi in questo caso specifico, allora si può fare il setter privata dichiarando esplicitamente:

private(set) lazy var foo : Int = { return 42 }() 

Questo è un buon compromesso tra l'immutabilità e la pigrizia.

+0

Il setter privato è sufficiente per me. Io uso spesso questo modello anche in C#. – MBulli

+0

Penso che questo sia equivalente a '' 'private (set) lazy var foo = 42'''. Se si segna il setter come privato non ha senso dichiarare il getter solo allo scopo di omettere il setter. –

+3

Non era un getter, è una pigra chiusura di istanziazione, ma non è necessario perché non contiene alcuna logica. Ecco perché 'private (set) lazy var foo = 42' funzionerà allo stesso modo. – Danchoys

5

È inoltre possibile utilizzare una variabile di supporto privata che inizializza pigramente:

var foo : Int { return _foo } 
private lazy var _foo :Int = { return 42 }() 
+3

Sebbene le risposte siano corrette, preferisco la risposta di Antonios in quanto non introduce un'altra proprietà. – MBulli

+0

Sebbene la risposta accettata al momento non funzioni, lo fa. – Barry

+0

@Barry la risposta accettata funziona ora (a partire da Xcode 7.1) –

2

E 'possibile fare questo con una proprietà calcolata e una struttura privata. Non c'è bisogno della parola chiave lazy sul valore var statico, in quanto assegnandole il risultato di un blocco è implicitamente pigro.

var foo: Int { 
    struct Holder { 
     static var value = { return 42 }() 
    } 
    return Holder.value 
} 
+0

Questo è intelligente e utile in alcuni casi, ma purtroppo non è utile quando il valore calcolato dipende dall'oggetto "self" come swift doesn Permettere alle strutture interne di chiudersi sull'ambito esterno. –

+0

@Daniel È un punto eccellente, tuttavia questo approccio funziona perfettamente nel contesto della domanda. – kevin

Problemi correlati