How do I create an enum from an Int in Kotlin? - kotlin

I have this enum:
enum class Types(val value: Int) {
FOO(1)
BAR(2)
FOO_BAR(3)
}
How do I create an instance of that enum using an Int?
I tried doing something like this:
val type = Types.valueOf(1)
And I get the error:
Integer literal does not conform to the expected type String

enum class Types(val value: Int) {
FOO(1),
BAR(2),
FOO_BAR(3);
companion object {
fun fromInt(value: Int) = Types.values().first { it.value == value }
}
}
You may want to add a safety check for the range and return null.

Enum#valueOf is based on name. Which means in order to use that, you'd need to use valueof("FOO"). The valueof method consequently takes a String, which explains the error. A String isn't an Int, and types matter. The reason I mentioned what it does too, is so you know this isn't the method you're looking for.
If you want to grab one based on an int value, you need to define your own function to do so. You can get the values in an enum using values(), which returns an Array<Types> in this case. You can use firstOrNull as a safe approach, or first if you prefer an exception over null.
So add a companion object (which are static relative to the enum, so you can call Types.getByValue(1234) (Types.COMPANION.getByValue(1234) from Java) over Types.FOO.getByValue(1234).
companion object {
private val VALUES = values()
fun getByValue(value: Int) = VALUES.firstOrNull { it.value == value }
}
values() returns a new Array every time it's called, which means you should cache it locally to avoid re-creating one every single time you call getByValue. If you call values() when the method is called, you risk re-creating it repeatedly (depending on how many times you actually call it though), which is a waste of memory.
Admittedly, and as discussed in the comments, this may be an insignificant optimization, depending on your use. This means you can also do:
companion object {
fun getByValue(value: Int) = values().firstOrNull { it.value == value }
}
if that's something you'd prefer for readability or some other reason.
The function could also be expanded and check based on multiple parameters, if that's something you want to do. These types of functions aren't limited to one argument.

If you are using integer value only to maintain order, which you need to access correct value, then you don't need any extra code. You can use build in value ordinal. Ordinal represents position of value in enum declaration.
Here is an example:
enum class Types {
FOO, //Types.FOO.ordinal == 0 also position == 0
BAR, //Types.BAR.ordinal == 1 also position == 1
FOO_BAR //Types.FOO_BAR.ordinal == 2 also position == 2
}
You can access ordinal value simply calling:
Types.FOO.ordinal
To get correct value of enum you can simply call:
Types.values()[0] //Returns FOO
Types.values()[1] //Returns BAR
Types.values()[2] //Returns FOO_BAR
Types.values() returns enum values in order accordingly to declaration.
Summary:
Types.values(Types.FOO.ordinal) == Types.FOO //This is true
If integer values don't match order (int_value != enum.ordinal) or you are using different type (string, float...), than you need to iterate and compare your custom values as it was already mentioned in this thread.

It really depends on what you actually want to do.
If you need a specific hardcoded enum value, then you can directly use Types.FOO
If you are receiving the value dynamically from somewhere else in your code, you should try to use the enum type directly in order not to have to perform this kind of conversions
If you are receiving the value from a webservice, there should be something in your deserialization tool to allow this kind of conversion (like Jackson's #JsonValue)
If you want to get the enum value based on one of its properties (like the value property here), then I'm afraid you'll have to implement your own conversion method, as #Zoe pointed out.
One way to implement this custom conversion is by adding a companion object with the conversion method:
enum class Types(val value: Int) {
FOO(1),
BAR(2),
FOO_BAR(3);
companion object {
private val types = values().associate { it.value to it }
fun findByValue(value: Int): Types? = types[value]
}
}
Companion objects in Kotlin are meant to contain members that belong to the class but that are not tied to any instance (like Java's static members).
Implementing the method there allows you to access your value by calling:
var bar = Types.findByValue(2) ?: error("No Types enum value found for 2")
Note that the returned value is nullable, to account for the possibility that no enum value corresponds to the parameter that was passed in. You can use the elvis operator ?: to handle that case with an error or a default value.

If you hate declaring for each enum type a companion object{ ... } to achieve EMotorcycleType.fromInt(...). Here's a solution for you.
EnumCaster object:
object EnumCaster {
inline fun <reified E : Enum<E>> fromInt(value: Int): E {
return enumValues<E>().first { it.toString().toInt() == value }
}
}
Enum example:
enum class EMotorcycleType(val value: Int){
Unknown(0),
Sport(1),
SportTouring(2),
Touring(3),
Naked(4),
Enduro(5),
SuperMoto(6),
Chopper(7),
CafeRacer(8),
.....
Count(9999);
override fun toString(): String = value.toString()
}
Usage example 1: Kotlin enum to jni and back
fun getType(): EMotorcycleType = EnumCaster.fromInt(nGetType())
private external fun nGetType(): Int
fun setType(type: EMotorcycleType) = nSetType(type.value)
private external fun nSetType(value: Int)
---- or ----
var type : EMotorcycleType
get() = EnumCaster.fromInt(nGetType())
set(value) = nSetType(value.value)
private external fun nGetType(): Int
private external fun nSetType(value: Int)
Usage example 2: Assign to val
val type = EnumCaster.fromInt<EMotorcycleType>(aValidTypeIntValue)
val typeTwo : EMotorcycleType = EnumCaster.fromInt(anotherValidTypeIntValue)

A naive way can be:
enum class Types(val value: Int) {
FOO(1),
BAR(2),
FOO_BAR(3);
companion object {
fun valueOf(value: Int) = Types.values().find { it.value == value }
}
}
Then you can use
var bar = Types.valueOf(2)

Protocol orientated way with type-safety
interface RawRepresentable<T> {
val rawValue: T
}
inline fun <reified E, T> valueOf(value: T): E? where E : Enum<E>, E: RawRepresentable<T> {
return enumValues<E>().firstOrNull { it.rawValue == value }
}
enum class Types(override val rawValue: Int): RawRepresentable<Int> {
FOO(1),
BAR(2),
FOO_BAR(3);
}
Usage
val type = valueOf<Type>(2) // BAR(2)
You can use it on non-integer type, too.

I would build the 'reverse' map ahead of time. Probably not a big improvement, but also not much code.
enum class Test(val value: Int) {
A(1),
B(2);
companion object {
val reverseValues: Map<Int, Test> = values().associate { it.value to it }
fun valueFrom(i: Int): Test = reverseValues[i]!!
}
}
Edit: map...toMap() changed to associate per #hotkey's suggestion.

try this...
companion object{
fun FromInt(v:Int):Type{
return Type::class.java.constructors[0].newInstance(v) as Type
}
}

This is for anyone looking for getting the enum from its ordinal or index integer.
enum class MyEnum { RED, GREEN, BLUE }
MyEnum.values()[1] // GREEN
Another solution and its variations:
inline fun <reified T : Enum<T>> enumFromIndex(i: Int) = enumValues<T>()[i]
enumFromIndex<MyEnum>(1) // GREEN
inline fun <reified T : Enum<T>> enumFromIndex(i: Int) = enumValues<T>().getOrNull(i)
enumFromIndex<MyEnum>(3) ?: MyEnum.RED // RED
inline fun <reified T : Enum<T>> enumFromIndex(i: Int, default: T) =
enumValues<T>().getOrElse(i) { default }
enumFromIndex(2, MyEnum.RED) // BLUE
It is an adapted version of another answer. Also, thanks to Miha_x64 for this answer.

Another option...
enum class Types(val code: Int) {
FOO(1),
BAR(2),
FOO_BAR(3);
companion object {
val map = values().associate { it.code to it }
// Get Type by code with check existing codes and default
fun getByCode(code: Int, typeDefault_param: Types = FOO): Types {
return map[code] ?: typeDefault_param
}
}
}
fun main() {
println("get 3: ${Types.getByCode(3)}")
println("get 10: ${Types.getByCode(10)}")
}
get 3: FOO_BAR
get 10: FOO

Related

What is the type of a Kotlin 'data class'?

I have a situation where I need to create a copy of data class object. I don't know in advance which of the many data classes I have will come in into the function. I do know, however, that only data classes will be used as input to this function.
This is what didn't work:
fun doSomething(obj: Any): Any {
obj.copy(...) // <- there's no 'copy' on Any
...
}
This is what I really like to do:
fun doSomething(obj: KAnyDataClass): KAnyDataClass {
obj.copy(...) // <- works, data classes have a 'copy' method
...
}
I'm not a Kotlin developer, but it looks like the language does not support dynamic dispatch or traits. You might find success with the dynamic type, which just turns off the type-checker so it won't yell at you for using a method that it doesn't know about. However this opens up the possibility of a runtime error if you pass an argument that actually doesn't have that method.
There is no class or interface for data classes, but we know from the documentation of data classes that there are derived functions componentN and copy in each data class.
We can use that knowledge to write an abstract copy method that calls the copy method of a given arbitrary data class using reflection:
fun <T : Any> copy(data: T, vararg override: Pair<Int, Any?>): T {
val kClass = data::class
if (!kClass.isData) error("expected a data class")
val copyFun = kClass.functions.first { it.name == "copy" }
checkParameters(override, kClass)
val vals = determineComponentValues(copyFun, kClass, override, data)
#Suppress("UNCHECKED_CAST")
return copyFun.call(data, *vals) as T
}
/** check if override of parameter has the right type and nullability */
private fun <T : Any> checkParameters(
override: Array<out Pair<Int, Any?>>,
kClass: KClass<out T>
) {
override.forEach { (index, value) ->
val expectedType = kClass.functions.first { it.name == "component${index + 1}" }.returnType
if (value == null) {
if (!kClass.functions.first { it.name == "component${index + 1}" }.returnType.isMarkedNullable) {
error("value for parameter $index is null but parameter is not nullable")
}
} else {
if (!expectedType.jvmErasure.isSuperclassOf(value::class))
error("wrong type for parameter $index: expected $expectedType but was ${value::class}")
}
}
}
/** determine for each componentN the value from override or data element */
private fun <T : Any> determineComponentValues(
copyFun: KFunction<*>,
kClass: KClass<out T>,
override: Array<out Pair<Int, Any?>>,
data: T
): Array<Any?> {
val vals = (1 until copyFun.parameters.size)
.map { "component$it" }
.map { name -> kClass.functions.first { it.name == name } }
.mapIndexed { index, component ->
override.find { it.first == index }.let { if (it !== null) it.second else component.call(data) }
}
.toTypedArray()
return vals
}
Since this copy function is generic and not for a specific data class, it is not possible to specify overloads in the usual way, but I tried to support it in another way.
Let's say we have a data class and element
data class Example(
val a: Int,
val b: String,
)
val example: Any = Example(1, "x")
We can create a copy of example with copy(example) that has the same elements as the original.
If we want to override the first element, we cannot write copy(example, a = 2), but we can write copy(example, 0 to 2), saying that we want to override the first component with value 2.
Analogously we can write copy(example, 0 to 3, 1 to "y") to specify that we want to change the first and the second component.
I am not sure if this works for all cases since I just wrote it, but it should be a good start to work with.

How to mix an upper bound with null values in a generic Kotlin class

I tried to derive a delegate class from AbstractList with an upper bound Comparable and want to use lists as delegate which can contain null values.
Here's my implementation:
package org.baier.test
class MyList<out T: Comparable<#kotlin.UnsafeVariance T>>(private val delegate: List<T>) : AbstractList<T>() {
override val size = delegate.size
override fun get(index: Int): T {
return delegate[index]
}
}
fun main() {
val delegate1: List<Int> = listOf(1, 2, 3, 4, 5)
val list1 = MyList(delegate1)
val delegate2: List<Int?> = listOf(1, 2, 3, null, 4, 5)
val list2 = MyList(delegate2)
}
In the main method I tried to instantiate the class Mylist with both a List and a List<Int?>.
Why do I get a compiler error for the latter one saing
"Type mismatch. Required:Comparable<Int?> Found: Int?"
Why is Int? not of type Comparable<Int?>?
Int is defined as a Comparable<Int>. An Int? is Comparable<Int>? but not a Comparable<Int?>? because Int does not specifically implement Comparable<Int?>.
There are at least a couple of reasons for this:
It's ambiguous whether null should be considered greater or less than any specific integer value.
You can't actually uses a nullable variable as a Comparable to sort something because you can't call compareTo() on null. For example (null as Int?)?.compareTo(1) would return null rather than -1 / 0 / 1 so you couldn't actually use it to sort something. Comparable.compareTo()'s contract is that it works the same in both directions, so this is impossible with a null value. You can define your own Comparable that works with a nullable value, which might have some uses, but not for sorting a list using the standard library sort functions.
If you're not using this class for sorting, you may want to define some other upper bound.
The reasons why it is not working are those already proposed by Tenfour04.
Anyway if you want to make it work also with nulls, you could try to say that your List is of type List<T?> and then define some kind of default for the get overriding when it happens to be null. Like the following:
class MyList<out T: Comparable<#kotlin.UnsafeVariance T>(private val delegate: List<T?>, private val nullValuesProvider: (Int) -> T) : AbstractList<T>() {
override val size = delegate.size
override fun get(index: Int): T {
return delegate[index] ?: nullValuesProvide(index)
}
}
or in alternative, a default value for nulls:
class MyList<out T: Comparable<#kotlin.UnsafeVariance T>(private val delegate: List<T?>, private val defaultIfNull: T) : AbstractList<T>() {
override val size = delegate.size
override fun get(index: Int): T {
return delegate[index] ?: defaultIfNull
}
}

What is the difference between Comparable and operator compareTo?

Lets say I have class A(val foo: Double).
I want to be be able to compare it to other A, Double, and Int.
If I implement Comparable, I can only compare it against one other object type.
override fun compareTo(other: A): Int {
return when {
this.foo == other.foo -> 0
this.foo > other.foo -> 1
else -> -1
}
}
But I've also seen extension functions overriding the compareTo operator.
operator fun A.compareTo(d: Double): Int {
return when {
this.foo == d -> 0
this.foo > d -> 1
else -> -1
}
}
What is the difference between these and what should I be using? I'm guessing if I want to compare it to multiple types then I have to use extension functions?
The Comparable interface comes from Java, and, as you have seen, is defined with only a compareTo( other) method, which only provides for comparing an object to another object of the same type.
As you have also noticed, the Kotlin extension functions are additional functions allowing you to compare an object to whatever you want, as long as you define the compareTo method to take an argument of the type to which you want to compare.
So, yes, if you want to compare an object to an object of a different type, you will need to write an appropriate extension function.
Of course, in Java, if you have control of the source code of the class, you can always add a custom compareTo method.
Comparable is a standard interface, it's the way you define a class as having some ordering, and every library that deals with ordering works with Comparable types. Basically, if you want to be able to order and compare your things using all the standard functions and anything anyone else might write, you need to implement the Comparable interface.
This works:
data class SportsTeam(val name: String) : Comparable<SportsTeam> {
override fun compareTo(other: SportsTeam): Int = when {
name == "best team" -> 1
other.name == "best team" -> -1
else -> 0
}
}
fun main(args: Array<String>) {
val best = SportsTeam("best team")
val worst = SportsTeam("worst team")
print("The winner is: ${maxOf(best, worst).name}")
}
but because maxOf takes a Comparable type, this won't work:
data class SportsTeam(val name: String)
fun SportsTeam.compareTo(other: SportsTeam): Int = when {
name == "best team" -> 1
other.name == "best team" -> -1
else -> 0
}
fun main(args: Array<String>) {
val best = SportsTeam("best team")
val worst = SportsTeam("worst team")
print("The winner is: ${maxOf(best, worst).name}")
}
Wenn you make your own objects you must implement Comparable interface and then override compareTo function
class MyClass : Comparable<MyClass> {
override fun compareTo(other: MyClass): Int {
// TODO Returns zero if this object is equal to the specified other object
}
}
You can also override an operator function, for example from Int class in kotlin
fun main(args: Array<String>) {
val a = 1
val b = "2"
println(a.compareTo(b))
}
operator fun Int.compareTo(i: String) : Int {
return if (this.toString() == i) {
0
} else {
1
}
}
I hope that's helpfull from you

Kotlin: store any type of function reference in a variable

Is it possible to have a variable that can holds any type function.
Like :
fun method1(par: Boolean){}
fun method2(par: Boolean) : Int{return 1}
fun method3(par: Boolean, par2: Boolean) : Int{return 1}
var funtionHolder : ((Any)->Any) ?= null //What should I write here?? so to hold any type of function
fun method4(){
.........
funtionHolder = ::method1 //getting compile time error
.........
funtionHolder = ::method2 //getting compile time error
.........
funtionHolder = ::method3 //getting compile time error
}
After holding the function_reference I need to invoke it later. So I need to holds it parameter type and state also.
You can hold them in a KFunction<Any> or its superclass KCallable<Any> because you know nothing about the parameter list and nothing about the return type, so you have to go to something that can reference at that level of abstraction. These instances can then be invoked more generically using the call() or callBy() methods. (this requires the kotlin-reflect dependency). To do something safer and to call like a normal function you'd have to cast back to the specific function type later.
If you want to avoid this, you'll need to unify your signatures to something you can point to with another function type (i.e. KFunction1 or KFunction2). Otherwise how you'll call this, what you'll do with it will be up to you at this point because you erased all the information that allows you to easily call the function.
val functionHolder1: KFunction<Any> = ::method1 // success!
val functionHolder2: KFunction<Any> = ::method2 // success!
val functionHolder3: KFunction<Any> = ::method3 // success!
You can then make a DeferredFunction class to hold these along with parameters you want to later pass, and then invoke it whenever in the future.
class DeferredFunction(val function: KFunction<Any>, vararg val params: Any?) {
#Suppress("UNCHECKED_CAST")
operator fun <T> invoke(): T {
return function.call(params) as T
}
}
fun whatever(name: String, age: Int): String {
return "$name of age $age"
}
val functionHolder = DeferredFunction(::whatever, "Fred", 65)
println(functionHolder<String>()) // "Fred of age 65"
You do not need the generic return type on the invoke function and could just make it return Any or call it as functionHolder<Any>() but it is nice if you know what to expect for the return. You can decide what to do there based on your actual use case. Also no need to special case for no parameters, just don't pass any, i.e. DeferredFunction(::otherFunc)
With reference from Jayson's answer, added extra code to hold the state of the function by using vararg and spread operator(*).
var functionHolder: KFunction<Any> ?= null
var paramsHolder : Array<out Any?> ?= null
fun hold(functionReference : KFunction<Any>, vararg args : Any?) {
this.functionHolder = functionReference
this.paramsHolder = args
}
fun release() {
if (functionHolder != null) {
if (paramsHolder != null) {
functionHolder?.call(*paramsHolder!!)
} else {
functionHolder?.call()
}
}
}
......
fun method3(par: Boolean, par2: Boolean) : Int{return 1}
......
hold(::method3, true, false)
release()//it works
No. Kotlin is static typed language and doesn't allow this. Else what happens when this is called?
functionHolder->invoke(3)
and when functionHolder is assigned a lamda that doesn't take parameter?

How to create a generic array filled with nulls in Kotlin?

I tried this, and the code didn't compile.
class GenericClass<T>() {
private var arr : Array<T>? = null
{
arr = Array<T>(10, { null })
}
}
There are two compiler errors reported in this code: one is about nullable types and another about generics.
Nullable types. Kotlin enforces a discipline of nullable references, and since T may be instantiated with, say, String making arr be of type Array, the compiler does not allow you to put nulls into this array. If you want nulls, you have to change the type to Array:
class GenericClass<T>() {
private var arr : Array<T?>? = null
{
arr = Array(10, { null }) // No need to specify type arguments again
}
}
Generics. The example above still has a compile-time error, because we are trying to construct an array of an unknown type T. Note that this problem exists in Java as well. Kotlin being compiled to JVM byte code entails two things:
generics type arguments are erased at runtime,
except for generic arguments of arrays.
This means that in the byte code Kotlin has to create an array of some concrete type, and not an unknown type T. It could create arrays of Objects whenever it sees Array, but this would not work, for example, in this case:
fun test() {
fun foo(srts: Array<String?>) {
// ...
}
val gc = GenericClass<String>()
foo(gc.arr)
}
Here, in the last line, we are trying to pass Object[] where String[] is expected, and get a runtime error.
This is why Kotlin refuses to create arrays of T. You can work around this problem by explicitly suppressing the type system, i.e. by using type casts:
class GenericClass<T>() {
val arr : Array<T?>
{
arr = Array<Any?>(10, { null }) as Array<T?>
}
}
Here we explicitly request creation of an array of Any (compiled to Object[]), and then type-cast it to an array of T. The compiler issues a warning, but obeys our will.
Note that the problematic example above remains, i.e. if you pass the array created this way where an array of strings is expected, it ill fail at run time.
method
val array : Array<T?> = kotlin.arrayOfNulls<T>(size)
from docs
/**
*Returns an array of objects of the given type with the given [size],
*initialized with null values.
*/
public fun <reified #PureReifiable T> arrayOfNulls(size: Int): Array<T?>
If you need to initialize array in the constructor, you can add an inline factory method and parametrize it using reified T. This solution is inspired by answer https://stackoverflow.com/a/41946516/13044086
class GenericClass<T> protected constructor(
private val arr : Array<T?>
) {
companion object {
inline fun <reified T>create(size: Int) = GenericClass<T>(arrayOfNulls(size))
}
}
fun main() {
val strs = GenericClass.create<String>(10)
...
}
Notice that the constructor is protected, because inline function can't access a private constructor.
If you need to create an array after the object is created, you can pass lambda that creates the array into the method. Lambda can be created inside of extension function, so information about type of the array is preserved. #PublishedApi annotation is used to encapsulate private method fill.
import GenericClass.Companion.fill
class GenericClass<T> {
private var arr : Array<T?>? = null
fun show() {
print(arr?.contentToString())
}
private fun fill(arrayFactory: (size: Int) -> Array<T?>) {
this.arr = arrayFactory(10)
}
#PublishedApi
internal fun `access$fill`(arrayFactory: (size: Int) -> Array<T?>) = fill(arrayFactory)
companion object {
inline fun <reified T>GenericClass<T>.fill() {
`access$fill`(arrayFactory = { size -> arrayOfNulls(size) })
}
}
}
fun main() {
val strs = GenericClass<String>()
strs.fill()
strs.show()
}
You could use a helper function as below:
#Suppress("UNCHECKED_CAST")
fun <T> genericArrayOfNulls(size: Int): Array<T?> {
return arrayOfNulls<Any?>(size) as Array<T?>
}