Search code examples
arrayskotlinlogic

Creating a Class that creates array of Int with elements between two args(intStart, intEnd)


Hi everybody and thanks for your time! I have an issue here. In a nutshell, i want to create a class an instance of which stores a data between two arguments of this class. Similar to "IntRange" class works. For instance: val r1 = IntRange(0,5) // output 0 1 2 3 4 5. Tried to explain as much as possible, English is not mouther tongue :) What i've tried:

fun main(args: Array<String>) {
    val ownArray = OwnIntRange(0,2).getNumbers()
    
}

public interface Counter{
    fun getNumbers(): Array<Int>
    var counter: Int
}

class OwnIntRange(val intMin: Int, val intMax: Int): Counter{
    override var counter = 0
    override fun getNumbers(): Array<Int> {

        for (number in intMin..intMax){
            getNumbers()[counter] = number
            counter++
        }
        return getNumbers()
    }
}

//result: StackOverflowError

if you could correct my approach i would be really happy. Any critics welcome!


Solution

  • The problem is that your getNumbers() function always calls itself at least once.  Which calls itself.  Which calls itself.  Which calls itself…  So it gets stuck in an endless series of nested calls, and runs out of stack space to store them.

    Recursion can be a valid technique, but you always need a termination condition, a point beyond which it stops calling itself and starts returning — which your code doesn't have.  However, recursion isn't needed at all in this case.

    I can't quite follow your intent in that implementation, but here's slightly different one that works:

    override fun getNumbers(): Array<Int> {
        val a = Array<Int>(intMax - intMin + 1){ 0 }
    
        for (number in intMin..intMax)
            a[number - intMin] = number
    
        return a
    }
    

    (Note that this doesn't use counter; it looks like that's not needed at all.)

    That that could be written much more simply (and slightly more efficiently), by making better use of the init parameter to the Array constructor:

    override fun getNumbers() = Array(intMax - intMin + 1){
        it + intMin
    }
    

    It's also not common (and arguably not a good idea) to include the type in your variable names; simply calling them e.g. min and max would be simpler and easier to read.  (It also wouldn't need renaming if you changed the type from Int to Long or whatever.)

    Of course, in production code you probably wouldn't need this class at all, as IntRange would do fine.  If you did need your own class, I'd look very seriously at whether a getNumbers() method was really needed, as there would almost certainly be better approaches that didn't create temporary arrays, e.g. by using the visitor pattern.