Sobes.tech
Middle

Čo je to reflexia a ako je implementovaná v Kotlin?

sobes.tech AI

Odpoveď od AI

Reflexia v Kotlin je možnosť skúmať vlastnosti objektov, tried a ich členov počas behu programu. Umožňuje získavať informácie o type objektu, jeho metódach, poliach, konštruktoch a anotáciách, ako aj dynamicky volať metódy a meniť hodnoty polí.

V Kotlin je reflexia implementovaná pomocou API v balíku kotlin.reflect. Pre prácu s reflexiou je potrebné pridať závislosť kotlin-reflect. Toto API poskytuje triedy reprezentujúce rôzne prvky jazyka:

  • KClass: reprezentuje triedu. Umožňuje získať názov triedy, zoznam konštruktorov, členov (metód a vlastností), nadtried a pod.
  • KCallable: všeobecné rozhranie pre funkcie a vlastnosti, ktoré je možné volať.
  • KFunction: reprezentuje funkciu. Umožňuje získať parametre, typ návratovej hodnoty a volať funkciu.
  • KProperty: reprezentuje vlastnosť (členskú premennú). Umožňuje získať typ vlastnosti, jej viditeľnosť, anotácie a získať alebo nastaviť hodnotu.

Na získanie reflexívnych objektov sa používajú operátory :: pre triedy, funkcie a vlastnosti, alebo metódy typu .java.kotlin na získanie KClass z Java Class.

Príklady použitia:

// Získanie KClass pomocou operátora ::class
val personClass: KClass<Person> = Person::class

// Získanie KClass z Java Class
val personJavaClass: Class<Person> = Person::class.java
val personKotlinClass: KClass<Person> = personJavaClass.kotlin

// Získanie zoznamu konštruktorov triedy
val constructors = personClass.constructors

// Získanie zoznamu členov triedy (vlastností a funkcií)
val members = personClass.members

// Získanie KFunction pre metódu
val sayHelloFunction: KFunction<*> = personClass.members.find { it.name == "sayHello" } as KFunction<*>

// Volanie metódy cez reflexiu
val personInstance = Person("Alice")
sayHelloFunction.call(personInstance)

// Získanie KProperty pre vlastnosť
val nameProperty: KProperty1<Person, String> = personClass.members.find { it.name == "name" } as KProperty1<Person, String>

// Získanie hodnoty vlastnosti cez reflexiu
val nameValue = nameProperty.get(personInstance)

// Nastavenie hodnoty vlastnosti cez reflexiu (pre meniteľné vlastnosti)
// val mutableNameProperty = personClass.members.find { it.name == "mutableName" } as KMutableProperty1<Person, String>
// mutableNameProperty.set(personInstance, "Bob")

Reflexia je užitočná pre:

  • Metaprogramovanie (ORM rámce, serializácia/deserializácia).
  • Vytváranie dynamických proxy a aspektov.
  • Testovanie (prístup k súkromným členom).
  • introspekciu počas behu.

Je dôležité pamätať, že použitie reflexie môže znižovať výkon a sťažovať kód, ako aj stať sa menej bezpečným kvôli obchádzaniu modifikátorov prístupu. Je potrebné ju používať vedome a tam, kde iné prístupy nie sú efektívne alebo možné.