Ce face public și internal
Kotlin are patru niveluri de vizibilitate: public, internal, protected și private. Dacă nu scrii nimic, declarația este public: vizibilă din orice cod care are acces la pachetul ei. De aceea public se scrie rar, de obicei doar în bibliotecile care activează modul -Xexplicit-api, unde orice API public trebuie marcat explicit.
internal înseamnă „vizibil în tot modulul”, dar nu în afara lui. Un modul este un set de fișiere compilate împreună: un modul Gradle sau Maven, un proiect din IntelliJ, sau fișierele date unei singure comenzi kotlinc. Așa o bibliotecă își poate folosi clasele ajutătoare în toate pachetele ei, fără ca utilizatorii bibliotecii să le vadă.
Java nu are „modul” în același sens: pe JVM, membrii internal devin public în bytecode, cu numele modificat ca să fie greu de apelat din Java. Pentru private și protected, vezi pagina dedicată.
Exemple
Exemplul 1: Declarații public și internal în același modul
Programul este un singur modul, deci main vede și clasa internal. O altă bibliotecă sau aplicație care ar folosi acest cod ar vedea doar Calculator și calculeazaTva.
// public implicit: vizibil pentru oricine folosește modulul
class Calculator {
fun calculeazaTva(pret: Double) = Rotunjire.laBani(pret * CotaTva.STANDARD)
}
// internal: doar pentru codul din acest modul
internal object CotaTva {
const val STANDARD = 0.21
}
internal object Rotunjire {
fun laBani(x: Double) = Math.round(x * 100) / 100.0
}
fun main() {
val c = Calculator()
println("TVA pentru 99,99 lei: ${c.calculeazaTva(99.99)} lei")
println("Cota folosită: ${CotaTva.STANDARD}")
}
Rezultat
TVA pentru 99,99 lei: 21.0 lei
Cota folosită: 0.21
Exemplul 2: Eroare din alt modul (nu rulează aici)
Două module: facturare (pachetul ro.firma.facturare, cu class Calculator publică și internal object CotaTva), compilat separat cu kotlinc -module-name facturare -d fact.jar, și modulul app de mai jos, compilat cu kotlinc app/Main.kt -cp fact.jar -module-name app. Calculator se vede, CotaTva nu.
// modulul :app
import ro.firma.facturare.Calculator
import ro.firma.facturare.CotaTva
fun main() {
println(Calculator().calculeazaTva(100.0))
println(CotaTva.STANDARD)
}
Rezultat la compilare
app/Main.kt:2:27: error: cannot access 'object CotaTva : Any': it is internal in file.
import ro.firma.facturare.CotaTva
^^^^^^^
app/Main.kt:6:13: error: cannot access 'object CotaTva : Any': it is internal in file.
println(CotaTva.STANDARD)
^^^^^^^
Greșeli frecvente
- Credința că
internalînseamnă „în același pachet”: în Kotlin înseamnă „în același modul”. Kotlin nu are vizibilitate de pachet ca Java. - Expunerea unui tip
internalprintr-o funcțiepublic(fun cota(): CotaTva): eroare'public' function exposes its 'internal' return type 'CotaTva'. - Scrierea lui
publicpeste tot din obișnuința din Java: este redundant, pentru că este valoarea implicită.
Comenzi înrudite
private și protected: private ascunde o declarație în clasa sau fișierul ei; protected o face vizibilă și în subclase.package și import: package stabilește numele pachetului unui fișier; import aduce în fișier clase și funcții din alte pachete.class: class declară o clasă: un tip nou care grupează date (proprietăți) și comportament (metode).kotlinc: Compilatorul Kotlin din linia de comandă: transformă fișierele .kt într-un program care rulează pe JVM.