Razmišljanje s Kotlinom
1. Uvod
Reflection je naziv za sposobnost pregledavanja, učitavanja i interakcije s klasama, poljima i metodama tijekom izvođenja. To možemo učiniti čak i kad ne znamo koje su one u vrijeme sastavljanja.
Ovo ima velik broj namjena, ovisno o tome što razvijamo. Na primjer, okviri poput Proljeća to jako koriste.
Podrška za to ugrađena je u JVM i stoga je implicitno dostupna za sve jezike temeljene na JVM-u. Međutim, neki JVM jezici imaju dodatnu podršku povrh onoga što je već dostupno.
2. Java Reflection
Dostupne su sve standardne konstrukcije Java Reflection i savršeno dobro rade s našim Kotlin kodom. To uključuje java.lang.Clasa klase kao i sve u java.lang.reflect paket.
Ako iz bilo kojeg razloga želimo koristiti standardne API-je Java Reflection, to možemo učiniti na potpuno isti način kao u Java-i. Na primjer, da bismo dobili popis svih javnih metoda u razredu Kotlin, učinili bismo:
MyClass :: class.java.methods
To se raščlanjuje na sljedeće konstrukcije:
- MyClass :: klasa daje nam predstavljanje klase Kotlin za Moj razred razred
- .Java daje nam java.lang.Clasa ekvivalent
- .metode je poziv na java.lang.Class.getMethods () metoda pristupa
Ovo će raditi potpuno isto bez obzira poziva li se s Jave ili Kotlina i poziva li se na Java ili Kotlin klasi. To uključuje specifične konstrukcije za Kotlin, poput klasa podataka.
klasa podataka ExampleDataClass (ime vala: String, omogućeno var: Boolean) ExampleDataClass :: class.java.methods.forEach (:: println)
Kotlin također pretvara vraćene tipove u Kotlinove reprezentacije.
U gore navedenom dobivamo a kotlin.Array na koji se možemo pozvati za svakoga().
3. Poboljšanja refleksije Kotlina
Iako možemo koristiti standardne API-je Java Reflection, nije svjestan svih proširenja koja Kotlin donosi na platformu.
Uz to, ponekad može biti pomalo neugodno koristiti u nekim situacijama. Kotlin donosi vlastiti API za razmišljanje koji možemo koristiti za rješavanje ovih problema.
Sve ulazne točke u Kotlin Reflection API koriste reference. Ranije smo vidjeli upotrebu :: razred dati referencu na definiciju klase. To ćemo također moći koristiti za dobivanje referenci na metode i svojstva.
3.1. Reference klase Kotlin
Kotlin Reflection API omogućuje pristup referenci klase. To se zatim može koristiti za introspekciju svih detalja klase Kotlin. To daje pristup referenci Java Class - java.lang.Clasa objekt - ali i na sve specifičnosti Kotlina.
Kotlin API za detalje klase usredotočen je na kotlin.reflect.KClass razred. Ovome se može pristupiti pomoću :: operator iz bilo kojeg naziva klase ili instance - npr. String :: klasa.
Inače, može mu se pristupiti metodom produženja java.lang.Class.kotlin ako Java Razred instanca nam je dostupna:
val listClass: KClass = List :: class val name = "Baeldung" val stringClass: KClass = name :: class val someClass: Class val kotlinClass: KClass = someClass.kotlin
Nakon što smo dobili a KClass Objekt, ima nekoliko jednostavnih stvari koje nam može reći o predmetnoj klasi. Neki od njih su standardni Java koncepti, a drugi su Kotlin specifični koncepti.
Na primjer, lako možemo saznati je li klasa apstraktna ili konačna, ali također možemo saznati je li klasa podatkovna ili prateća klasa:
val stringClass = Niz :: klasa assertEquals ("kotlin.String", stringClass.qualifiedName) assertFalse (stringClass.isData) assertFalse (stringClass.isCompanion) assertFalse (stringClass.isAbstract) assertTrue (stringClass.isfisal)
Imamo i načina kretanja po hijerarhiji razreda. U Javi već možemo prijeći iz klase u njezinu superklasu, sučelja i vanjsku klasu u koju je zatvorena - ako je prikladno.
Kotlin ovome dodaje mogućnost dobivanja pratećeg objekta za proizvoljnu klasu i Objekt primjer za klasu Object:
println (TestWithCompanion :: class.companionObject) println (TestWithCompanion :: class.companionObjectInstance) println (TestObject :: class.objectInstance)
Možemo stvoriti nove primjerke klase i iz reference klase, na približno isti način kao na Javi:
val listClass = ArrayList :: klasa val list = listClass.createInstance () assertTrue (popis je ArrayList)
Alternativno, možemo pristupiti konstruktorima i koristiti eksplicitni ako je potrebno. Sve su to reference na metode kako je raspravljeno u sljedećem odjeljku.
Na vrlo sličan način možemo dobiti pristup svim metodama, svojstvima, proširenjima i ostalim članovima klase:
val bigDecimalClass = BigDecimal :: class println (bigDecimalClass.constructors) println (bigDecimalClass.functions) println (bigDecimalClass.memberProperties) println (bigDecimalClass.memberExtentionFunctions)
3.2. Reference metode Kotlina
Osim što mogu komunicirati s nastavom, također možemo komunicirati s metodama i svojstvima.
To uključuje svojstva klase - definirana s val ili var, standardne metode klase i funkcije najviše razine. Kao i prije, ovo jednako dobro djeluje na kodu napisanom na standardnoj Javi kao i na kodu napisanom u Kotlinu.
Na potpuno isti način kao i kod predavanja, možemo dobiti referencu na metodu ili svojstvo pomoću:: operater.
Ovo izgleda potpuno isto kao u Javi 8 za dobivanje reference metode i možemo je koristiti na potpuno isti način. Međutim, u Kotlinu se ova referenca metode također može koristiti za dobivanje informacija o odrazu cilja.
Nakon što smo dobili referencu za metodu, možemo je nazvati kao da je doista riječ o metodi. Ovo je poznato kao pozivna referenca:
val str = "Zdravo" val lengthMethod = str :: length assertEquals (5, lengthMethod ())
Također možemo dobiti više detalja o samoj metodi, na isti način kao i za nastavu. To uključuje i standardne Java detalje, kao i specifične detalje Kotlina, na primjer, je li metoda operater ili ako je u redu:
val byteInputStream = String :: byteInputStream assertEquals ("byteInputStream", byteInputStream.name) assertFalse (byteInputStream.isSuspend) assertFalse (byteInputStream.isExternal) assertTrue (byteInputStreamis).
Uz ovo, putem ove reference možemo dobiti više informacija o ulazima i izlazima metode.
To uključuje detalje o vrsti povrata i parametrima, uključujući Kotlin specifične detalje - poput nulibilnosti i neobaveznosti.
val str = "Hello" val metoda = str :: byteInputStream assertEquals (ByteArrayInputStream :: class.starProjectedType, method.returnType) assertFalse (method.returnType.isMarkedNullable) assertEquals (1, method.parameters.size) assertTrue (method.parameters.size) assertTrue (method.parameters.size) assertTrue (method.parameters.size) assertTrue (method.parameters.size) assertTrue (method.parameters.size) 0] .isO optional) assertFalse (method.parameters [0] .isVararg) assertEquals (Charset :: class.starProjectedType, method.parameters [0] .type)
3.3. Kotlin reference nekretnine
To potpuno isto vrijedi i za Svojstva, iako su očito detalji koji se mogu dobiti različiti. Svojstva nas umjesto toga mogu obavijestiti jesu li konstante, kasno inicijalizirane ili promjenjive:
lateinit var mutableProperty: String val mProperty = this :: mutableProperty assertEquals ("mutableProperty", mProperty.name) assertTrue (mProperty.isLateinit) assertFalse (mProperty.isConst) assertTrue (mProperty je KMutableProperty)
Imajte na umu da koncept svojstava također funkcionira u bilo kojem kodu koji nije Kotlin. Oni su identificirani poljima koja slijede JavaBeans konvencije u vezi s metodama dobivanja i postavljanja.
To uključuje nastavu u standardnoj knjižnici Java. Na primjer, Bacljivo razred ima Svojstvo Dohvatljivo.poruka na osnovu činjenice da postoji metoda getMessage () definirana u njemu.
Stvarnom svojstvu možemo pristupiti putem izloženih referenci metoda - the getter i seter metode. The seter dostupan je samo ako radimo s a KMutableProperty - tj. imovina je proglašena kao var, dok je getter je uvijek dostupan.
Oni su izloženi na lakši način za korištenje putem dobiti() i postavi () metode. The getter i seter vrijednosti su stvarne reference metode, što nam omogućuje rad s njima potpuno isti kao i bilo koja druga referenca metode:
val prop = this :: mutableProperty assertEquals (String :: class.starProjectedType, prop.getter.returnType) prop.set ("Hello") assertEquals ("Hello", prop.get ()) prop.setter ("World") assertEquals ("Svijet", prop.getter ())
4. Sažetak
Ovaj članak daje pregled nekih stvari koje se mogu postići refleksijom u Kotlinu, uključujući i način interakcije i razliku od mogućnosti refleksije ugrađene u standardni jezik Java.
Svi primjeri dostupni su na GitHubu.