Kotlin reflection get property value

Introduction to the reflection feature in Kotlin

In programming, reflection is a programming language’s ability to inspect and interact with statically defined classes, functions, and properties during runtime.

The feature is particularly useful when you receive an object instance of an unknown class.

By using reflection, you can check if a particular object has a certain method, and call that method when it exists.

To use reflection in Kotlin, you need to include the kotlin-reflect library in your project:

The library contains the runtime component required for using Kotlin reflection features.

Next, let’s see how you can get class, function, and property references using Kotlin reflection feature.

Kotlin reflection — class reference

Suppose you have a Dog class with the following definitions:

 To get the class reference in Kotlin, you can use the class literal syntax ::class as shown below:
 Alternatively, you can get the class reference from an object instance by using the same ::class syntax on the instance:
Getting the class reference from an object is also known as a bounded class reference.

Once you have the class reference, you can access the properties of the reference to find out more about that class.

For example, you can find the name of the class and check if that class is a data class:

In Kotlin, the class reference is identified as the Kclass type which stands for Kotlin class.

You can check the Kclass documentation for all properties and methods you can access to find out about the class from its reference.

Aside from inspecting the class, the Kclass also has some interesting abilities. The createInstance() method, for example, allows you to create a new object from the class reference:

But keep in mind that the createInstance() method only works when the class has a constructor with optional or no parameter.

An error will be thrown when no constructor fulfills the criteria.

Accessing Kotlin class reference methods

You can also get access to the methods of the class reference regardless of their access modifier.

This means even private functions of a class can be accessed from its reference.

The memberFunctions property of Kclass stores all methods of the class as a Collection :

  The output will be as follows:
Next, you can call the class function from its reference as follows:
  First, you need to use the find() function to retrieve the function reference.

Then, check if the function reference is found using the null-safe call.

When the reference is found, use the call() method from the function reference Kfunction type.

The first argument of the call() method must be an instance of the class reference, which is why myDog object is passed into the method.

When your function is private , you need to change the isAccessible property of the function reference as true first before calling the function:

  And that’s how you access the methods of a class using its reference.

Accessing Kotlin class reference properties

The properties of a Kotlin class reference can be accessed the same way you access its methods.

The properties of a class are stored in memberProperties as a Collection .

For example, you can get the name property value of the myDog instance as follows:

A property reference is an instance of KProperty type. The value of the property is retrieved by calling the getter() method.

To change the value of the name property, you need to cast the property into KMutableProperty first as shown below:

The KMutableProperty holds the setter() method, which you need to call to set the value of the property.

Now you’ve learned how to access methods and properties from a class reference.

Next, let’s look at how you can get a function reference with Kotlin reflection

Kotlin reflection — function reference

You can get a reference to a named Kotlin function by using the :: operator.

The funRef above will be an instance of Kfunction type, which represents a function with introspection capabilities.

Conclusion

Now you’ve learned what the Kotlin reflection feature is and how it works with some examples. Reflection is a powerful feature that’s only used for specific requirements.

Because of its ability to find inspect a source code, it’s frequently used when developing a framework or library for further development.

JUnit and Spring frameworks are notable for using reflection in their source code.

The library author won’t know the classes and functions created by the user. Reflection allows the framework to deal with classes and functions without knowing about them in advance.

Take your skills to the next level ⚡️

I’m sending out an occasional email with the latest tutorials on programming, web development, and statistics. Drop your email in the box below and I’ll send new stuff straight into your inbox!

About

Hello! This website is dedicated to help you learn tech and data science skills with its step-by-step, beginner-friendly tutorials.
Learn statistics, JavaScript and other programming languages using clear examples written for people.

Type the keyword below and hit enter

Источник

Reflection

Reflection is a set of language and library features that allows you to introspect the structure of your program at runtime. Functions and properties are first-class citizens in Kotlin, and the ability to introspect them (for example, learning the name or the type of a property or function at runtime) is essential when using a functional or reactive style.

Kotlin/JS provides limited support for reflection features. Learn more about reflection in Kotlin/JS.

JVM dependency

On the JVM platform, the Kotlin compiler distribution includes the runtime component required for using the reflection features as a separate artifact, kotlin-reflect.jar . This is done to reduce the required size of the runtime library for applications that do not use reflection features.

To use reflection in a Gradle or Maven project, add the dependency on kotlin-reflect :

If you don’t use Gradle or Maven, make sure you have kotlin-reflect.jar in the classpath of your project. In other supported cases (IntelliJ IDEA projects that use the command-line compiler or Ant), it is added by default. In the command-line compiler and Ant, you can use the -no-reflect compiler option to exclude kotlin-reflect.jar from the classpath.

Class references

The most basic reflection feature is getting the runtime reference to a Kotlin class. To obtain the reference to a statically known Kotlin class, you can use the class literal syntax:

The reference is a KClass type value.

On JVM: a Kotlin class reference is not the same as a Java class reference. To obtain a Java class reference, use the .java property on a KClass instance.

Bound class references

You can get the reference to the class of a specific object with the same ::class syntax by using the object as a receiver:

You will obtain the reference to the exact class of an object, for example, GoodWidget or BadWidget , regardless of the type of the receiver expression ( Widget ).

Callable references

References to functions, properties, and constructors can also be called or used as instances of function types.

Function references

When you have a named function declared as below, you can call it directly ( isOdd(5) ):

Alternatively, you can use the function as a function type value, that is, pass it to another function. To do so, use the :: operator:

Here ::isOdd is a value of function type (Int) -> Boolean .

:: can be used with overloaded functions when the expected type is known from the context. For example:

Alternatively, you can provide the necessary context by storing the method reference in a variable with an explicitly specified type:

If you need to use a member of a class or an extension function, it needs to be qualified: String::toCharArray .

Even if you initialize a variable with a reference to an extension function, the inferred function type will have no receiver, but it will have an additional parameter accepting a receiver object. To have a function type with a receiver instead, specify the type explicitly:

Example: function composition

Consider the following function:

It returns a composition of two functions passed to it: compose(f, g) = f(g(*)) . You can apply this function to callable references:

Property references

To access properties as first-class objects in Kotlin, use the :: operator:

The expression ::x evaluates to a KProperty0 type property object. You can read its value using get() or retrieve the property name using the name property. For more information, see the docs on the KProperty class.

For a mutable property such as var y = 1 , ::y returns a value with the KMutableProperty0 type which has a set() method:

A property reference can be used where a function with a single generic parameter is expected:

To access a property that is a member of a class, qualify it as follows:

For an extension property:

Interoperability with Java reflection

On the JVM platform, the standard library contains extensions for reflection classes that provide a mapping to and from Java reflection objects (see package kotlin.reflect.jvm ). For example, to find a backing field or a Java method that serves as a getter for a Kotlin property, you can write something like this:

To get the Kotlin class that corresponds to a Java class, use the .kotlin extension property:

Constructor references

Constructors can be referenced just like methods and properties. You can use them wherever the program expects a function type object that takes the same parameters as the constructor and returns an object of the appropriate type. Constructors are referenced by using the :: operator and adding the class name. Consider the following function that expects a function parameter with no parameters and return type Foo :

Using ::Foo , the zero-argument constructor of the class Foo , you can call it like this:

Callable references to constructors are typed as one of the KFunction subtypes depending on the parameter count.

Bound function and property references

You can refer to an instance method of a particular object:

Instead of calling the method matches directly, the example uses a reference to it. Such a reference is bound to its receiver. It can be called directly (like in the example above) or used whenever a function type expression is expected:

Compare the types of the bound and the unbound references. The bound callable reference has its receiver «attached» to it, so the type of the receiver is no longer a parameter:

val isNumber: (CharSequence) -> Boolean = numberRegex::matches val matches: (Regex, CharSequence) -> Boolean = Regex::matches

A property reference can be bound as well:

You don’t need to specify this as the receiver: this::foo and ::foo are equivalent.

Bound constructor references

A bound callable reference to a constructor of an inner class can be obtained by providing an instance of the outer class:

Источник

Kotlin Reflection Getting values of all properties of a class

Given Example class extending BaseExample class with some properties:

open class BaseExample(val baseField: String) class Example(val field1: String, val field2: Int, baseField: String): BaseExample(baseField) < val field3: String get() = "Property without backing field" val field4 by lazy < "Delegated value" >private val privateField: String = "Private value" > 

One can get hold of all properties of a class:

val example = Example(field1 = "abc", field2 = 1, baseField = "someText") example::class.memberProperties.forEach < member ->println("$ -> $") > 

Running this code will cause an exception to be thrown. Property private val privateField is declared private and calling member.get(example) on it will not succeed. One way to handle this it to filter out private properties. To do that we have to check the visibility modifier of a property’s Java getter. In case of private val the getter does not exist so we can assume private access.

The helper function and it’s usage might look like this:

fun isFieldAccessible(property: KProperty1): Boolean < return property.javaGetter?.modifiers?.let < !Modifier.isPrivate(it) >?: false > val example = Example(field1 = "abc", field2 = 1, baseField = "someText") example::class.memberProperties.filter < isFieldAccessible(it) >.forEach < member ->println("$ -> $") > 

Another approach is to make private properties accessible using reflection:

example::class.memberProperties.forEach < member ->member.isAccessible = true println("$ -> $") > 

pdf

PDF — Download Kotlin for free

Источник

Читайте также:  Php путь до временных файлов
Оцените статью