Smart casting è un meccanismo in cui il compilatore Kotlin "abbassa" automaticamente il tipo dopo aver verificato un certo tipo o null. Questo consente di utilizzare le proprietà e i metodi del tipo in cui è stato effettuato il casting senza conversione esplicita.
fun demo(x: Any) { if (x is String) { println(x.length) // x è automaticamente castato a String } }
Funziona con:
is / !is (ad esempio, in if o when)if (x != null))whenNon funziona:
val str: String? = getString() if (str != null) println(str.length) // smart cast
val something: Any get() = fetch() if (something is String) { println(something.length) // Errore: smart cast non possibile }
È possibile contare su smart cast per proprietà open o var della classe all'interno dei metodi?
No! Smart cast funziona solo con variabili locali e proprietà val nelle classi finali. Per proprietà open o var, il compilatore non è sicuro che il valore possa cambiare da altri thread o da sottoclassi. Per loro è necessario un cast manuale o una variabile locale.
open class Base { open var maybeString: Any? = "abc" fun check() { if (maybeString is String) { // println(maybeString.length) // Errore: Smart cast non possibile val asString = maybeString as String println(asString.length) // Cast esplicito } } }
Storia
In un progetto, per la logica degli schermi, sono state utilizzate proprietà model open var. Il programmatore si aspettava di ottenere smart-cast dopo il controllo
if (model is SomeType), ma durante la compilazione ha dovuto fare tutto manualmente, il che ha peggiorato la leggibilità e ha aumentato la duplicazione del codice a causa della mancata conoscenza delle limitazioni di smart cast su var/open.
Storia
Quando si ottenevano dati tramite un getter (ad esempio, attraverso un delegato o una validazione), lo smart cast non ha funzionato. Lo sviluppatore non ha compreso le ragioni e ha impiegato diverse ore per il debug, finché non ha scoperto che il compilatore non applica smart cast a tali getter, poiché possono restituire valori diversi tra le chiamate.
Storia
In un progetto, durante l'elaborazione di valori nullable tramite
if (obj != null)lo smart cast ha funzionato all'interno del ramo, mentre parallelizzando il codice si sono verificati NullPointerException a causa di accessi al di fuori dell'area di garanzia. Questo ha mostrato una comprensione insufficiente dell'azione locale di smart cast e delle peculiarità degli scenari multithread di lavoro con variabili nullable.