Elmélkedés Kotlinnal
1. Bemutatkozás
A tükrözés az osztályok, mezők és módszerek futás közbeni ellenőrzésének, betöltésének és azokkal való interakció képességének a neve. Ezt akkor is megtehetjük, ha nem tudjuk, hogy mik azok a fordítás idején.
Ennek számos felhasználása van, attól függően, hogy mit fejlesztünk. Például az olyan keretrendszerek, mint a Spring, erősen használják.
Ennek támogatása beépül a JVM-be, és így implicit módon elérhető az összes JVM-alapú nyelv számára. Egyes JVM nyelvek azonban a már elérhetőeken felül extra támogatást nyújtanak.
2. Java reflexió
Az összes standard Java Reflection konstrukció elérhető és tökéletesen működik a Kotlin kóddal. Ide tartozik a java.lang.Osztály osztály, valamint minden a java.lang.reflect csomag.
Ha bármilyen okból a szabványos Java Reflection API-kat akarjuk használni, akkor azt ugyanúgy megtehetjük, mint a Java-ban. Például egy Kotlin osztály összes nyilvános módszerének felsorolásához tennénk:
MyClass :: class.java.methods
Ez a következő konstrukciókra bontható:
- MyClass :: osztály megadja nekünk a Kotlin osztály reprezentációját Az osztályom osztály
- .Jáva megadja nekünk a java.lang.Osztály egyenértékű
- .mód felhívás a java.lang.Class.getMethods () accessor módszer
Ez pontosan ugyanúgy fog működni, függetlenül attól, hogy Java-ból vagy Kotlin-ből hívják-e meg, és hogy Java vagy Kotlin osztályon hívják-e. Ez magában foglalja a Kotlin-specifikus konstrukciókat, például az adatosztályokat.
adatosztály ExampleDataClass (val név: String, var engedélyezve: Boolean) ExampleDataClass :: class.java.methods.forEach (:: println)
Kotlin a visszaküldött típusokat konvertálja Kotlin reprezentációkká is.
A fentiekben a kotlin. Array amelyen felhívhatjuk az egyes().
3. Kotlin Reflection Enhancements
Bár használhatjuk a standard Java Reflection API-kat, nem ismeri az összes kiterjesztést, amelyet Kotlin a platformra hoz.
Ezenkívül esetenként kissé kényelmetlen lehet használni bizonyos helyzetekben. Kotlin hozza a saját reflexiós API-ját, amelyet felhasználhatunk ezeknek a problémáknak a megoldására.
A Kotlin Reflection API összes belépési pontja használja a Referenciákat. Korábban láttuk a ::osztály hogy utalást adjon az osztály definíciójára. Ezt arra is felhasználhatjuk, hogy referenciákat kapjunk a módszerekre és tulajdonságokra.
3.1. Kotlin osztály referenciák
A Kotlin Reflection API hozzáférést biztosít egy osztály referenciához. Ezt lehet felhasználni a Kotlin osztály teljes részleteinek felkutatására. Ez hozzáférést biztosít a Java osztály hivatkozáshoz - a java.lang.Osztály objektumot -, hanem a Kotlin összes részletét is.
A Kotlin API osztályrészletekhez a kotlin.reflect.KClass osztály. Ehhez a :: operátor bármely osztálynévből vagy példányból - például. Húr :: osztály.
Alternatív megoldásként a kiterjesztés módszerével érhető el java.lang.Class.kotlin ha Java Osztály példány elérhető számunkra:
val listClass: KClass = List :: class val name = "Baeldung" val stringClass: KClass = name :: class val someClass: Class val kotlinClass: KClass = someClass.kotlin
Miután megszereztük a KClass objektum, van néhány egyszerű dolog, amit elmondhat a kérdéses osztályról. Ezek némelyike standard Java-koncepció, mások Kotlin-specifikus fogalmak.
Például könnyen megtudhatjuk, hogy egy osztály elvont vagy végleges, de azt is megtudhatjuk, hogy az osztály adatosztály vagy társosztály:
val stringClass = String :: class assertEquals ("kotlin.String", stringClass.qualifiedName) assertFalse (stringClass.isData) assertFalse (stringClass.isCompanion) assertFalse (stringClass.isAbstract) assertTrue (stringClass.isFinal) assertFalse (stringClASS.assFalse)
Arra is van módunk, hogy mozoghassunk az osztályhierarchiában. A Java-ban már elmozdulhatunk egy osztályról a szuperosztályára, az interfészekre és a külső osztályra, amelybe zárt - adott esetben.
Kotlin ehhez hozzáteszi a Companion Object megszerzésének képességét egy tetszőleges osztályhoz, és a Tárgy egy Object osztály példánya:
println (TestWithCompanion :: class.companionObject) println (TestWithCompanion :: class.companionObjectInstance) println (TestObject :: class.objectInstance)
Új osztálypéldányokat hozhatunk létre egy osztályreferenciából is, ugyanúgy, mint a Java-ban:
val listClass = ArrayList :: osztály val list = listClass.createInstance () assertTrue (a lista ArrayList)
Alternatív megoldásként hozzáférhetünk a kivitelezőkhöz, és szükség esetén egy kifejezettet használhatunk. Mindezek a következő szakaszban tárgyalt módszer-referenciák.
Nagyon hasonló módon hozzáférhetünk az osztály összes módszeréhez, tulajdonságához, kiterjesztéséhez és az osztály többi tagjához:
val bigDecimalClass = BigDecimal :: class println (bigDecimalClass.constructors) println (bigDecimalClass.functions) println (bigDecimalClass.memberProperties) println (bigDecimalClass.memberExtensionFunctions)
3.2. Kotlin-módszer hivatkozások
Amellett, hogy kapcsolatba léphet az Osztályokkal, kölcsönhatásba léphetünk a Módszerekkel és a Tulajdonságokkal is.
Ide tartoznak az osztály tulajdonságai - a val vagy var, szabványos osztályú módszerek és legfelső szintű függvények. Az előzőekhez hasonlóan ez ugyanolyan jól működik a standard Java-ban írt kódokon, mint a Kotlinban írt kódoknál.
Pontosan ugyanúgy, mint az osztályoknál, a. használatával hivatkozást szerezhetünk egy módszerre vagy tulajdonságra:: operátor.
Ez pontosan ugyanúgy néz ki, mint a Java 8-ban a metódus referencia megszerzéséhez, és pontosan ugyanúgy használhatjuk. Ugyanakkor Kotlinban ez a módszerre való hivatkozás felhasználható a célról reflexiós információk megszerzésére is.
Miután megszereztük a módszer referenciáját, úgy hívhatjuk, mintha valóban ez lenne a kérdéses módszer. Ez hívható hivatkozásként ismert:
val str = "Hello" val lengthMethod = str :: length assertEquals (5, lengthMethod ())
Magáról a módszerről is további részleteket kaphatunk, ugyanúgy, mint az órákon. Ez magában foglalja mind a standard Java-részleteket, mind a Kotlin-specifikus részleteket, például, ha a módszer egy operátor vagy ha mégis Sorban:
val byteInputStream = Karakterlánc :: byteInputStream assertEquals ("byteInputStream", byteInputStream.name) assertFalse (byteInputStream.isSuspend) assertFalse (byteInputStream.isExternal) assertTrue (byteInputStream.isInis) AssertFalse
Ezen felül ezen a referencián keresztül kaphatunk további információkat a módszer be- és kimeneteiről.
Ez magában foglalja a visszatérési típus és a paraméterek részleteit, beleértve a Kotlin-specifikus részleteket - például a semmisséget és az opcionális tulajdonságokat.
val str = "Hello" val method = str :: byteInputStream assertEquals (ByteArrayInputStream :: class.starProjectedType, method.returnType) assertFalse (method.returnType.isMarkedNullable) assertEquals (1, method.parameters.size) assertTrue (metódus.parameters.size) assertTrue (módszer. 0] .isOptional) assertFalse (method.parameters [0] .isVararg) assertEquals (Charset :: class.starProjectedType, method.parameters [0] .type)
3.3. Kotlin Property References
Ez pontosan ugyanúgy működik a Tulajdonságok esetében isbár nyilvánvalóan a megszerezhető részletek különbözőek. A tulajdonságok ehelyett tájékoztathatnak bennünket, ha konstansok, későn inicializáltak vagy módosíthatók:
lateinit var mutableProperty: String val mProperty = this :: mutableProperty assertEquals ("mutableProperty", mProperty.name) assertTrue (mProperty.isLateinit) assertFalse (mProperty.isConst) assertTrue (mProperty is KMutableProperty)
Vegye figyelembe, hogy a Tulajdonságok fogalma minden nem Kotlin kódban is működik. Ezeket olyan mezők azonosítják, amelyek betartják a JavaBeans konvencióit a getter és setter módszerekkel kapcsolatban.
Ez magában foglalja a Java szabványos könyvtár osztályait is. Például a Dobható osztály rendelkezik tulajdonsággal Dobható.üzenet annak a ténynek az alapján, hogy létezik módszer getMessage () meghatározza benne.
A tényleges Tulajdonhoz hozzáférhetünk a kitett módszer hivatkozásokon keresztül - a getter és szetter mód. A szetter csak akkor érhető el, ha a KMutableProperty - azaz az ingatlant úgy nyilvánították var, míg a getter mindig elérhető.
Ezek könnyebben használható módon vannak kitéve a kap() és készlet() mód. A getter és szetter az értékek tényleges módszer referenciák, lehetővé téve számunkra, hogy pontosan ugyanúgy dolgozzunk velük, mint bármely más módszer referencia:
val prop = this :: mutableProperty assertEquals (String :: class.starProjectedType, prop.getter.returnType) prop.set ("Hello") assertEquals ("Hello", prop.get ()) prop.setter ("Világ") assertEquals ("Világ", prop.getter ())
4. Összefoglalás
Ez a cikk áttekintést nyújt azokról a dolgokról, amelyeket a reflexióval el lehet érni Kotlinban, beleértve azt is, hogy miként hat egymással a szabványos Java nyelvbe beépített reflexiós képességekkel, és miben különbözik azoktól.
Az összes példa elérhető a GitHub oldalon.