L'operatore as in Kotlin viene utilizzato per il casting esplicito dei tipi (cast). Esistono due varianti: as e as?. Il primo solleva un'eccezione, il secondo è più sicuro. Questo strumento è importante per lavorare con il polimorfismo, oltre che per la migrazione dei dati e l'interazione con API esterne.
In Java, per il casting dei tipi si utilizza l'operatore cast (TargetType)obj, che genera un ClassCastException in caso di errore. Kotlin ha sviluppato questo concetto, aggiungendo il cast sicuro (as?), il che ha reso più comodo e esplicito gestire la nullability e gli errori di runtime.
Il casting rigido dei tipi in un grande progetto è pericoloso: se il tipo non corrisponde, il programma si blocca (ClassCastException). È necessario ridurre tale comportamento senza errori silenziosi o NPE. È importante separare qualitativamente le situazioni in cui un errore deve essere gestito e quando è corretto restituire semplicemente null.
Kotlin fornisce due operatori:
as: casting rigido del tipo, genera ClassCastException se i tipi non corrispondono.as?: casting sicuro — restituisce null se il cast non è possibile.val x: Any = "Hello, Kotlin!" val s1: String = x as String // Ok, x è String val s2: String? = x as? String // Ok, x è String val n: Int? = x as? Int // n = null, cast sicuro
as solleva ClassCastException in caso di errore.as? restituisce null, riducendo gli errori critici.Controlla sempre 'as' il tipo a runtime?
Sì, se il cast è effettuato con tipi non compatibili, si verifica ClassCastException. Tuttavia, per alcune conversioni non esplicite, come tra Int e Float, tale casting non avviene — la conversione idiomatica in Kotlin avviene tramite metodi (toInt, toFloat).
È possibile utilizzare 'as' con un tipo nullable in un tipo non-null?
Sì, ma bisogna fare attenzione: se il valore risulta null, verrà sollevata un'eccezione. Qualsiasi casting di un tipo nullable a non-nullable senza verifica può portare a un errore di runtime.
val x: String? = null val y: String = x as String // solleverà ClassCastException!
Qual è la differenza tra 'is' e 'as'?
'is' è l'operatore di controllo dei tipi. Restituisce true/false, non effettua il casting del tipo. 'as' effettua effettivamente il casting del tipo, e se non è possibile, solleva un'eccezione (o restituisce null se viene utilizzato 'as?'). Spesso sono usati insieme per un casting sicuro:
if (x is String) { val s: String = x // smart cast }
as senza controllo del tipo, che porta a ClassCastException.Nel modulo di parsing dei dati, tutti gli oggetti vengono analizzati tramite as, ad esempio, obj as Double. Se i dati sono errati, l'applicazione si arresta con ClassCastException.
Pro:
Contro:
Viene utilizzata la costruzione smart-cast (tramite is) o il casting sicuro (as?):
val price = (obj as? Double) ?: 0.0
Pro:
Contro: