Rzutowanie i kontrola typów

Omawiając dopasowanie wzorców w kotlinie użyliśmy konstrukcji when. W ramach niej pojawił się operator is, który jest operatorem sprawdzającym typ zmiennej i odpowiada, plus minus, instanceof z Javy. To czego nie mieliśmy okazji dotychczas sprawdzić to mechanizm śledzenia typu.

Śledzenie i automatyczne rzutowanie

Przeanalizujemy mały programik:

Listing 1. Przykład śledzenia typu

fun main(args: Array<String>) {

    val s:Any = "Hello"

    if(s is String)
        println(s.length)
    else
        println(s)
}

Dzięki użyciu is w wyrażeniu warunkowym kompilator może wywnioskować, że jeżeli wyrażenie jest prawdziwe, to zmienna jest danego typu i może ją bezpiecznie rzutować. Zatem w danym bloku kodu zmienna będzie miała inny typ. Mechanizm ten ma jednak pewne ograniczenia:

  • Lokalne niezmienne val – zawsze będą rzutowane,
  • właściwości niezmienne val – nie będą rzutowane jeżeli można rozszerzać, są oznaczone jako open, lub mają ręcznie napisane gettery,
  • lokalne zmienne var – jeżeli pomiędzy sprawdzeniem, a użyciem są efektywnie finalne,
  • właściwości zmienne var – nigdy, ponieważ mogą być zmienione w dowolnym momencie przez kod zewnętrzny.

Samodzielne rzutowanie

Trochę inaczej ma się sytuacja, gdy samodzielnie chcemy rzutować daną zmienną. W tym celu możemy użyć operatorów as oraz as?. Pierwszy z nich w przypadku niezgodności typów zwróci, klasycznie, CCE. Nie akceptuje on wartości null. Drugi z operatorów akceptuje wartość null, zachowana jest tu konwencja związana ze zmiennymi, które mogą być null. W przypadku przekazania takiej wartości zwróci null.

Zachowanie tych operatorów ilustruje poniższy program:

Listing 2. Użycie as i as?

fun main(args: Array<String>) {

    val s:Any = "Hello"

    println((s as String).length)
    println((null as? String))

}

Podsumowanie

Mechanizm śledzenia i automatycznego rzutowania jest, jak wiele elementów języka, nastawiony na redukcję ilości kodu, który musimy napisać. Nawet jego ograniczenia nie są jakoś specjalnie bolesne. Samodzielne rzutowanie… serio?

Napisz odpowiedź

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax