Kotlin's reflection: Simple variable extraction out of String - kotlin

I've read about reflection in both Kotlin and Java documentation & getattr in Python examples but they all seem to lack my use case:
I have variables of type multableLiveData<boolean> like repetitionOfElementsInNewExerciseAllowed in a ViewModel class (Android programming) that I need to update from a different class like HomeFragment.
My unsexy approach was the following function in ViewModel:
fun updateBoolElement (boolElementToUpdate:String, valueToUpdateWith:Boolean){
when (boolElementToUpdate){
"repetitionOfElementsInNewExerciseAllowed" -> repetitionOfElementsInNewExerciseAllowed.value=valueToUpdateWith
}
}
Instead of this I'm striving for a recursive approach to extract the variable's name whose value I want to change out of the string boolElementToUpdate like this (pseudo code):
fun updateBoolElement (boolElementToUpdate:String, valueToUpdateWith:Boolean){
getAttributeReferenceByName(boolElementToUpdate).value = valueToUpdateWith
}
The way I would like to reuse the function is by calling it with different varible names then like
sharedViewModel.updateBoolElement("repetitionOfElementsInNewExerciseAllowed",repetitionOfElementsInNewExerciseAllowed)
or more abstractly
sharedViewModel.updateBoolElement("newVariableName",newBoolValue)
Is reflection or any other structure in Kotlin capable of doing such wizardry? Thanks for any hint!

Related

Create an object of random class in kotlin

I learned java and python in high school and I became very comfortable with python. I have recently started to learn kotlin, mainly for fun (the keyword for defining a function is fun so it has to be a fun language, right), but I have a little problem.
Let's suppose I have a hierarchy of classes for Chess pieces:
abstract class Piece {
...
}
class Rook : Piece() {
...
}
class Bishop : Piece() {
...
}
.
.
.
I am taking input from the user to generate the board, so if the user types r, I need to create a Rook object, if he types b, I need to create a Bishop etc.
In python, I'd probably use a dictionary that maps the input string to the corresponding class, so I can create an object of the correct type:
class Piece:
...
class Rook(Piece):
...
class Bishop(Piece):
...
.
.
.
input_map = {
'r': Rook,
'b': Bishop,
...
}
s = input_map[input()]() # use user input as key and create a piece of the correct type
I was really amazed by this pattern when I discovered it. In java, I had to use a switch case or a bunch of if else if to achieve the same result, which is not the end of the world, especially if I abstract it into a separate function, but it's not as nice as the python approach.
I want to do the same thing in kotlin, and I was wondering if there is a similar pattern for kotlin since it's a modern language like python (I know, I know, python isn't new, but I think it's very modern). I tried to look online, but it seems like I can't store a class (class, not an object) in a variable or a map like I can in python.
Am I wrong about it? Can I use a similar pattern in kotlin or do I have to fall back to the when statement (or expression)?
If I am not mistaken, a similar pattern could be achieved in java using reflection. I never got to learn reflection in java deeply, but I know it's a way to use classes dynamically, what I can do for free in python. I also heard that in java, reflection should be used as a last resort because it's inefficient and it's considered "black magic" if you understand my meaning. Does it mean that I need to use reflection to achieve that result in kotlin? And if so, is it recommended to use reflection in kotlin, and is it efficient?
I'd like to know how I can approach this problem, and I accept multiple answers and additional solutions I didn't come up with. Thanks in advance.
This can be done without reflection.
You can map the input characters to the constructors:
val pieceConstructorsByKeyChar = mapOf(
'r' to ::Rook,
'b' to ::Bishop,
// etc.
)
Getting values from a map gives you a nullable, since it's possible the key you supply isn't in the map. Maybe this is fine, if when you use this you might be passing a character the player typed that might not be supported. Then you would probably handle null by telling the player to try again:
val piece: Piece? = pieceConstructorsByKeyChar[keyPressed]?.invoke()
Or if you do the look-up after you've already checked that it's a valid key-stroke, you can use !! safely:
val piece: Piece = pieceConstructorsByKeyChar[keyPressed]!!()
Yes you can use similiar approach with Kotlin. Kotlin has many features and supports reflection. Let me write an example about your problem.
Firstly create your classes that will be generate by user input.
abstract class Piece
class Rook : Piece()
class Bishop : Piece()
Create your class map
val inputMap = mapOf(
"r" to Rook::class.java,
"b" to Bishop::class.java
)
Create an instance what you want using newInstance function. If your input map doesn't contains key you gave then it will return null.
val rook = inputMap["r"]?.newInstance()
val bishop = inputMap["b"]?.newInstance()
// null
val king = inputMap["k"]?.newInstance()
Also you can write your custom extensions to create new objects.
fun <T> Map<String, Class<out T>>.newInstance(key: String) = this[key]?.newInstance()
// Create an instance with extension function
inputMap.newInstance("r")

Utils class in Kotlin

In Java, we can create an utilities class like this:
final class Utils {
public static boolean foo() {
return false;
}
}
But how to do this in Kotlin?
I try using functions inside object:
object Utils {
fun foo(): Boolean {
return false
}
}
But when call this method from Java code it need to add INSTANCE. Ex: Utils.INSTANCE.foo().
Then I change to declare it as top-level function (without class or object):
#file:JvmName("Utils")
#file:JvmMultifileClass
fun foo(): Boolean {
return true
}
Then I can call Utils.foo() from Java code. But from Kotlin code I got Unresolved reference compiler error. It only allow be to use foo() function directly (without Utils prefix).
So what is the best approach for declaring utils class in Kotlin?
The last solution you've proposed is actually quite idiomatic in Kotlin - there's no need to scope your function inside anything, top level functions are just fine to use for utilities, in fact, that's what most of the standard library consists of.
You've used the #JvmName annotation the right way too, that's exactly how you're supposed to make these top level functions easily callable for Java users.
Note that you only need #JvmMultifileClass if you are putting your top level functions in different files but still want them to end up grouped in the same class file (again, only for Java users). If you only have one file, or you're giving different names per file, you don't need this annotation.
If for some reason you want the same Utils.foo() syntax in both Java and Kotlin, the solution with an object and then #JvmStatic per method is the way to do that, as already shown by #marianosimone in this answer.
You'd need to use #JvmStatic for that:
In Kotlin:
object Utils {
#JvmStatic
fun foo(): Boolean = true
}
val test = Utils.foo()
In Java:
final boolean test = Utils.foo()
Note that the util class you used in Java was the only way to supply additional functions there, for anything that did not belong to a particular type or object. Using object for that in Kotlin does not make any sense. It isn't a singleton, right?
The second approach you mentioned is rather the way to go for utility functions. Internally such functions get translated to static ones and as you can see they become the static util classes in Java you are searching for, as you can't have standalone functions in Java without a class or enum. In Kotlin itself however they are just functions.
Some even count utility classes to the anti-patterns. Functions on the other hand make totally sense without a class or object whose name hasn't so much meaning anyway.

Kotlin - lambda to return list of member variables

Preface: This is something I'm not sure Kotlin can do, but I feel like it should be able to do.
Question: Is it possible to return a list composed from another lists' member variables without creating a separate function, via lambda, mapping, or otherwise?
I have a Kotlin inner class that has a name string representing a physical COM port. I have a routine that will poll for available COM ports on a device, and will return a list of the available port name strings for selection.
inner class ComPort() {
val portName: String = "something"
... }
...
ComPortSelectBox.setItems(*getComPortNames())
...
private fun getComPortNames(): Array<String> {
val names: ArrayList<String> = ArrayList()
for(comPort in availableComPorts)
{ names + comPort.portName }
return names.toTypedArray()
}
Because getComPortNames() is only used in the one location, I would love to simplify this call into something equivalent to getComPortNames that I can use inline within .setItems(...). Is this possible within Kotlin? If so, how would one do it?
I'm not sure what availableComPorts actually is, but it looks like Iterable. If so then you may do something like:
ComPortSelectBox.setItems(*availableComPorts.map(ComPort::portName).toTypedArray())
UPD. You did't mention which Java you're using. I assumed it is Java 8.

Kotlin equivalent of class properties, constructors, empty parameter constructors, getters and setters

I am currently practicing in developing kotlin and as of now I seem to get confused with kotlin's class structure.
this is a code in java
//properties
private String var;
//constructor
public SampleClass(String var){
this.var = var;
}
public SampleClass(){
}
//getters and setters
public String getVar(){
return this.var;
}
public String setVar(String var){
this.var = var;
}
what's the kotlin equivalent of this ?
This is the equivalent Kotlin code for your Java code:
class SampleClass(var `var`: String? = null)
There are a few things to note:
Your Java snippet above omits the wrapping class SampleClass code
Your setVar() indicates that it returns a String, but it's actually void. I assume you intended for it to have a void return type.
Your property var is not ideal for Kotlin, because it's a reserved word. That's why we have to escape it with backticks. (It could also be kind of confusing in Java 10, since var is a reserved type name there now).
Here's why this one-liner is equivalent to the Java listing.
The constructor part - the part between the parentheses - can be used to accept constructor arguments, but by putting the Kotlin keyword var at the beginning, we tell Kotlin that we want this to also be a property. Kotlin will create a getter and setter for it.
The String? part makes this property of type nullable String.
Instead of creating two different constructors, we just give our var property argument a default value of null by using = null. When creating this class from Java, it'll still show up as two constructors.
If you're using IntelliJ or Android Studio, you can tell it to convert any Java class to Kotlin. Just open the class file, and go to the Code menu, and choose Convert Java file to Kotlin file. It won't necessarily generate very idiomatic code (e.g., it might create two constructors instead of using a default for the constructor argument), but it'll get you started.
For "what is Kotlin equivalent of some code in Java", there is an universal answer: copy the Java code and paste it into a Kotlin file in IDEA/Android Studio. Or convert the entire file.
On the web, you can use https://try.kotlinlang.org/#/Kotlin%20Koans/Introduction/Java%20to%20Kotlin%20conversion/Task.kt.

Kotlin extension functions vs member functions?

I am aware that extension functions are used in Kotlin to extend the functionality of a class (for example, one from a library or API).
However, is there any advantage, in terms of code readability/structure, by using extension functions:
class Foo { ... }
fun Foo.bar() {
// Some stuff
}
As opposed to member functions:
class Foo {
...
fun bar() {
// Some stuff
}
}
?
Is there a recommended practice?
When to use member functions
You should use member functions if all of the following apply:
The code is written originally in Kotlin
You can modify the code
The method makes sense to be able to use from any other code
When to use extension functions
You should use extension functions if any of the following apply:
The code was originally written in Java and you want to add methods written in Kotlin
You cannot change the original code
You want a special function that only makes sense for a particular part of the code
Why?
Generally, member functions are easier to find than extension functions, as they are guaranteed to be in the class they are a member of (or a super class/interface).
They also do not need to be imported into all of the code that uses them.
From my point of view, there are two compelling reasons to use extension functions:
To "extend" the behaviour of a class you're not the author of / can't change (and where inheritance doesn't make sense or isn't possible).
To provide a scope for particular functionality. For example, an extension function may be declared as a freestanding function, in which case it's usable everywhere. Or you may choose to declare it as a (private) member function of another class, in which case it's only usable from inside that class.
It sounds like #1 isn't a concern in your case, so it's really more down to #2.
Extension functions are similar to those you create as a utility functions.
A basic example would be something like this:
// Strings.kt
fun String.isEmail() : Boolean {
// check for email pattern and return true/false
}
This code can be written as a utility function in Java like this:
class StringUtils {
public static boolean isEmail(String email) {
// check for email pattern and return true/false
}
}
So what it essentially does is, calling the same function with the object you call on will be passed as the first parameter to the argument. Like the same function I have given example of in Java.
If you want to call the extension function created in kotlin from java, you need to pass the caller as the first argument. Like,
StringsKt.isEmail("example#example.com")
As per the documentation,
Extensions do not actually modify classes they extend. By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on variables of this type.
They are simply static functions with the caller as the first argument and other parameters followed by it. It just extends the ability for us to write it that way.
When to create extension functions?
When you don't have access to that class. When that class belongs to some library you have not created.
For primitive types. Int, Float, String, etc.
The another reason for using extension function is, you don't have to extend that class in order to use the methods, as if they belong to that class (but not actually part of that class).
Hope it makes a bit clear for you..
As mentioned in other answers, extension functions are primarily used in code that you can't change - maybe you want to change complex expression around some library object into easier and more readable expression.
My take would be to use extension functions for data classes. My reasoning is purely philosophical, data classes should be used only as data carriers, they shouldn't carry state and by themselves shouldn't do anything. That's why I think you should use extension function in case you need to write a function around data class.