Yisus Threepwood
Yisus Threepwood

Reputation: 318

Kotlin - Creating a function for comparing any kind of number

I have the Kotlin object declaration bellow, with a detected smell (duplicate code)

object Random {

    internal fun generatePositiveFloat(
        leftLimit: Float = Float.MIN_VALUE,
        rightLimit: Float = Float.MAX_VALUE
    ): Float {
        if (leftLimit < 0) {
            throw InvalidAlgorithmParameterException("
                Left limit can't be negative"
            )
        } else if (rightLimit <= leftLimit) {
            throw InvalidAlgorithmParameterException(
                "Right limit can't be less or equal than left limit"
            )
        }
        return Random().nextFloat()
     }

    internal fun generatePositiveShort(
        leftLimit: Short = 0,
        rightLimit:  Short = Short.MAX_VALUE
    ): Short {
        if (leftLimit < 0) {
            throw InvalidAlgorithmParameterException(
                "Left limit can't be negative"
            )
        } else if (rightLimit <= leftLimit) {
            throw InvalidAlgorithmParameterException(
                "Right limit can't be less or equal than left limit"
            )
        }
        return ThreadLocalRandom.current().nextInt(
            leftLimit.toInt(),
            rightLimit.toInt()
        ).toShort()
}

Any idea for taking out this duplicate code to a private function?

My idea is something like this...

private fun validatePositiveLimits(
    leftLimit: Number,
    rightLimit: Comparable<Number>) {

    if (leftLimit as Comparable<Number> < 0) {
        throw InvalidAlgorithmParameterException(
            "Left limit can't be negative"
        )
    } else if (rightLimit <= leftLimit) {
        throw InvalidAlgorithmParameterException(
            "Right limit can't be less or equal than left limit"
        )
    }
}

... but I'm having trouble comparing leftLimit with 0 (leftLimit as Comparable < 0).

I get ClassCastException trying to cast integer to short and trying to cast integer to float.

Thanks so much.

Upvotes: 2

Views: 148

Answers (2)

s1m0nw1
s1m0nw1

Reputation: 81879

Some simple generics can provide a solution here:

private fun <T : Comparable<T>> checkConditions(left: T, right: T, leftLowerBound: T) {
    if (left < leftLowerBound) {
        throw InvalidAlgorithmParameterException(
            "Left limit can 't be negative"
        )
    } else if (right <= left) {
        throw InvalidAlgorithmParameterException(
            "Right limit can't be less or equal than left limit"
        )
    }
}

Invoked like this for Float:

checkConditions(leftLimit, rightLimit, 0F)

And like this for Short:

checkConditions(leftLimit, rightLimit, 0.toShort())

Upvotes: 2

null
null

Reputation: 11849

You can pass in 0 as an explicit argument.

private fun <T> validatePositiveLimits(zero: T, left: T, right: T) where T : Number, T : Comparable<T> {
    if (left < zero) {
        throw IllegalArgumentException("Left limit can't be negative")
    } else if (right <= left) {
        throw IllegalArgumentException("Right limit can't be less or equal than left limit")
    }
}

Upvotes: 1

Related Questions