Home > Back-end >  Kotlin: How to define a variable whose type depends on the input?
Kotlin: How to define a variable whose type depends on the input?

Time:06-25

I have a function in Kotlin which takes a particular string as input. Depending on the input, I want to create a variable of a specific type and do some computations on it.

For example,

fun compute(input: String): Any{
    if(input=="2d"){
        var point: Point2D;// Points2D - x: int, y: int
        //initilize and do some computations
        return point.findDistanceFromOrigin()
    }else if(input=="2d-1"){
        var point: Point2DWithP1AsOrigin;// Point2DWithP1AsOrigin - x: int, y: int
        //initilize and do some computations
        return point.findDistanceFromOrigin()
    }else if(input=="2d-2"){
        var point: Point2DWithP2AsOrigin;
        //initilize and do some computations
        return point.findDistanceFromOrigin()
    }
    .
    .
    .
}

You can see in the above example, I want to initilize the type of point depending on the input and do computation and return.

All the if-else conditions have the same code except for the definition of the variable. How can I put all this in a single block with something like this:

var point: if(input=="2d) Point2D::class else if(input=="2d-1") Point2DWithP1AsOrigin::class.....

How can I do that?

CodePudding user response:

You could do something like this

fun compute(input: String): Any{
    val point: MyPoint = when(input) {
        "2d" -> Point2D()
        "2d-1" -> Point2DWithP1AsOrigin()
        "2d-2" -> Point2DWithP2AsOrigin()
        else -> Point2D() //fallback is necessary
    }
    //initilize and do some computations
    return point.findDistanceFromOrigin()
}

But then it's essential that all those classes share the same interface. Because they need to have the same methods in order to do the same operations on them. For example like this:

class Point2D : MyPoint {
    override fun findDistanceFromOrigin() = 5
}

class Point2DWithP1AsOrigin : MyPoint{
    override fun findDistanceFromOrigin() = 6
}

class Point2DWithP2AsOrigin : MyPoint{
    override fun findDistanceFromOrigin() = 7
}

interface MyPoint {
    fun findDistanceFromOrigin() : Int
}

CodePudding user response:

You can store constructor references and then invoke required one

fun main() {
    val constructors = mapOf(
        "2d"   to ::Point2D,
        "2d-1" to ::Point2DWithP1AsOrigin,
        "2d-2" to ::Point2DWithP2AsOrigin,
    )

    val type = "2d-2"
    val constructor = constructors[type] ?: throw IllegalArgumentException("$type not supported")
    val point = constructor()

    println(point::class)
}

Output

class Point2DWithP2AsOrigin
  • Related