Sobes.tech
Middle

Kaip užtikrinti tipų saugumą Kotlin?

sobes.tech AI

Atsakymas iš AI

Tipų saugumas Kotlin'e yra užtikrinamas kelių pagrindinių mechanizmų dėka:

  1. Ne-null tipų sistema: Kotlin skiria nuorodinius tipus, kurie gali priimti reikšmę null (pažymėti ? pabaigoje tipo pavadinimo), ir tuos, kurie to padaryti negali. Kompiliatorius reikalauja aiškių null patikrinimų arba saugių iškvietimų (?.) ir operatorių (?:, !!).

    // Nuoroda, kuri negali būti null
    val nonNullableString: String = "Hello"
    
    // Nuoroda, kuri gali būti null
    var nullableString: String? = "World"
    nullableString = null // Leidžiama
    
    // Kompiliatoriaus klaida: reikalingas null apdorojimas
    // val length = nullableString.length
    
    // Saugi iškvietimas
    val length: Int? = nullableString?.length
    
    // Elvis operatorius
    val safeLength: Int = nullableString?.length ?: 0
    
  2. Protingi kastai (Smart Casts): Kompiliatorius automatiškai konvertuoja kintamojo tipą if, when, while, for ir kituose išraiškose po tipo arba null patikrinimo.

    fun printLength(obj: Any) {
        if (obj is String) {
            // Šio bloko viduje, kompiliatorius žino, kad obj yra String
            println("String ilgis yra ${obj.length}")
        }
    }
    
    fun processNullableString(str: String?) {
        if (str != null) {
            // Šio bloko viduje, kompiliatorius žino, kad str nėra null
            println("String nėra null, ilgis yra ${str.length}")
        }
    }
    
  3. Generiniai tipai: Kotlin palaiko generikus, kurie leidžia kurti klases, sąsajas ir funkcijas, dirbančias su įvairiais tipais, užtikrinant tipų saugumą kompiliacijos metu.

    class Box<T>(val item: T)
    
    fun printItem(box: Box<String>) {
        // Kompiliatorius žino, kad item yra String
        println(box.item.uppercase())
    }
    
  4. Kovariantiškumas (out) ir kontravariantiškumas (in): Leidžia tiksliau apibrėžti, kaip gali būti naudojami subtipai bendruose tipuose, užkertant kelią tipų nesuderinamumo klaidoms kompiliacijos metu.

    interface Source<out T> {
        fun nextT(): T
        // fun consumeT(t: T) // Kompiliatoriaus klaida
    }
    
    interface Sink<in T> {
        // fun produceT(): T // Kompiliatoriaus klaida
        fun consumeT(t: T)
    }
    
  5. Sealed klasės: Atstovauja apribotą klasės hierarchiją, kurioje visi pogrupiai yra žinomi kompiliacijos metu. Tai leidžia kompiliatoriui patikrinti when išraiškų pilnumą su sealed klasės pogrupiais, užtikrinant visų galimų atvejų apdorojimą.

    sealed class Result {
        data class Success(val data: String) : Result()
        data class Error(val code: Int) : Result()
    }
    
    fun handleResult(result: Result) {
        when (result) {
            is Result.Success -> println("Duomenys: ${result.data}")
            is Result.Error -> println("Klaida: ${result.code}")
            // Be 'else', kompiliatorius garantuoja visų pogrupių apdorojimą
        }
    }
    

Šie mechanizmai veikia kartu, leidžiantys anksti aptikti daugelį galimų klaidų, susijusių su tipais, dar prieš paleidžiant programą.