isf
isf

Reputation: 13

How to fix "Unresolved reference" error in Kotlin?

So I'm learning some cool plain Kotlin by making a blackjack game called DeadJack (Dead simple Blackjack). Here's the code:

class DeadJack(name: String = "Joe") {
    private val name: String = name
    private var number: Number = 0

    fun hit() {
        val rand = (0..10).random()
        if (number < 12) { // <--- Error in here
            // Code stopped here
        }
    }
}

Then I get this Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: .. error, I tried using IntelliJ's quick fix but it's just added some function with a TODO inside them (which I, who just started learning kotlin last night, can't understand).
Can I get some help? Thanks!

Upvotes: 1

Views: 2011

Answers (2)

gidds
gidds

Reputation: 18547

Short answer: use a concrete type such as Int instead of Number.

Number is an interface, and although it's implemented by many numeric classes (Int, Short, Byte, Long, Float, Double, BigInteger, BigDecimal, &c), it's very limited and not very useful in practice. About all you can do with it is convert it to standard numeric types — it has toFloat(), toInt(), &c methods — but it provides no way to do arithmetic, comparison, or other numeric operations.

In this case, the specific error is because Number is not Comparable, and so you can't use it in combination with the < operator.

It's not very clear why Number is so weak. I suspect the interface was something of an afterthought. Also, there are issues with the result types of any operations: what would be the result type of adding, say, a Byte and a Short? A Byte or Short would risk overflow; but to yield an Int would either need a huge matrix of method overloads, or a bunch of special cases in the type system. You can't even return the ‘biggest’ type each time, as both Long and Double can store values the other can't.

In fact, Kotlin is stricter about numeric types than Java or C, which both do some automatic conversions (‘numeric promotions’) where the intent is clear. Because those conversions can cause obscure bugs, Kotlin forces you to be more explicit about them.

So in general, it's better to stick to a concrete type in your code. (If you're providing an interface for other people to use, you could accept a Number as a parameter, but then immediately convert it to the concrete type you're using internally. But even that's not a great idea, since that conversion could be lossy.)

Upvotes: 2

Jo&#227;o Dias
Jo&#227;o Dias

Reputation: 17460

The problem is that number is a Number and 12 is an Int, which can't be compared like that. Either you make number as Int:

class DeadJack(name: String = "Joe") {
    private val name: String = name
    private var number = 0

    fun hit() {
        val rand = (0..10).random()
        if (number < 12) { 

        }
    }
}

Or you use number.toInt() while comparing:

class DeadJack(name: String = "Joe") {
    private val name: String = name
    private var number: Number = 0

    fun hit() {
        val rand = (0..10).random()
        if (number.toInt() < 12) {

        }
    }
}

Upvotes: 0

Related Questions