Chiar dacă Kotlin posedă cel mai inteligent sistem de Smart Casts din industrie (transformă automat o referință verificată cu if (x is String) în tipul concret), compilatorul nu poate deduce în mod nativ ce se întâmplă în interiorul unei funcții externe de validare:
fun verificaText(text: String?) {
if (text.isNullOrBlank()) throw IllegalArgumentException()
}
fun main() {
val s: String? = "Kotlin"
verificaText(s)
// Fără contracte, compilatorul NU știe că 's' nu mai poate fi null aici!
// println(s.length) // EROARE fără contracte!
}
Pentru a rezolva această deconectare, Kotlin introduce Contractele de Funcție (Kotlin Contracts) prin blocul contract { ... }, permițând unei funcții să comunice explicit compilatorului K2 garanțiile pe care le oferă la ieșire.
import kotlin.contracts.*
// Funcție utilitară de validare cu contract explicit:
@OptIn(ExperimentalContracts::class)
fun valideazaNenul(valoare: Any?) {
contract {
// Promisiune către compilatorul K2:
// Dacă această funcție se returnează normal (fără a arunca excepție),
// atunci 'valoare' este garantat diferită de NULL!
returns() implies (valoare != null)
}
if (valoare == null) {
throw IllegalArgumentException("Eroare critică: valoarea nu poate fi nulă!")
}
}
fun testSmartCast(input: String?) {
valideazaNenul(input)
// Datorită contractului, K2 activează automat Smart Cast:
println("Lungimea este: ${input.length}") // 100% sigur, 'input' este tratat ca String nenulabil!
}
Contractul callsInPlace pentru Inițializarea Variabilelor val
Un alt contract esențial informează compilatorul despre frecvența cu care o funcție lambda este executată:
@OptIn(ExperimentalContracts::class)
inline fun executaRapid(block: () -> R): R {
contract {
// Garantează că 'block' este apelat EXACT o singură dată pe loc:
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
fun calcul() {
val rezultat: Int // Variabilă imutabilă neinițializată
executaRapid {
rezultat = 42 // Permis! Compilatorul știe că block-ul rulează EXACT o dată!
}
println(rezultat)
}