Kotlin Compilation Error : None of the following functions can be called with the arguments supplied
Asked Answered
I

5

28

I have a class whose constructor takes 2 int parameters (null values are allowed). Following is the compilation error.

None of the following functions can be called with the arguments supplied: 
public final operator fun plus(other: Byte): Int defined in kotlin.Int
public final operator fun plus(other: Double): Double defined in kotlin.Int
public final operator fun plus(other: Float): Float defined in kotlin.Int
public final operator fun plus(other: Int): Int defined in kotlin.Int
public final operator fun plus(other: Long): Long defined in kotlin.Int
public final operator fun plus(other: Short): Int defined in kotlin.Int

Here is the NumberAdder class.

class NumberAdder (num1 : Int?, num2 : Int?) {

    var first : Int? = null
    var second : Int? = null

    init{
    first = num1
    second = num2
    }

fun add() : Int?{

    if(first != null && second != null){
        return first + second
    }

    if(first == null){
        return second
    }

    if(second == null){
        return first
    }

    return null
}

}

How can I resolve this issue? I want to return null if both are null. If one of them is null, return the other, and otherwise return the sum.

Interstadial answered 30/5, 2017 at 7:2 Comment(3)
Note this is almost the same as the simpler fun add = first?:0 + second?:0. Only difference being that it wont return null when both are null.Mylo
@MichaelAnderson Same compilation error fun add(first : Int?, second : Int?) : Int? = first?:0 + second?:0Interstadial
Sorry - it was just a parenthesis issue fun add():Int = (first:?0) + (second:?0) works for me.Mylo
S
13

Because first and second are vars, they will not be smart cast to non-null types when you do the if-test. Theoretically, the values can be changed by another thread after the if-test and before the +. To solve this, you can assign them to local vals before you do the if-tests.

fun add() : Int? {
    val f = first
    val s = second

    if (f != null && s != null) {
        return f + s
    }

    if (f == null) {
        return s
    }

    if (s == null) {
        return f
    }

    return null
}
Summerville answered 30/5, 2017 at 7:14 Comment(3)
Solution works. But i didn't understand why assigning variable to a constant works here?Interstadial
@Interstadial The value of a val can not be changed. Kotlin is therefore able to smart cast them to non-null types when you do the if-test. Even though first and second can be changed during the duration of the function, f and s will stay constant.Summerville
Got it. Thanks :)Interstadial
C
4

The easiest fix for your code is to use val instead of var:

class NumberAdder (num1 : Int?, num2 : Int?) {

    val first : Int?
    val second : Int?

    init{
        first = num1
        second = num2
    }
...

I used here that Kotlin allows a val to be assigned in the constructor.

Calves answered 30/5, 2017 at 10:47 Comment(1)
Variability affects the smart casting. It is well explained in the @marstrain's answerCalves
K
1

I experienced a similar issue with assertEquals.

My code was

assertEquals(
       expeted = 42, // notice the missing c 
       actual = foo()
)

After I've fixed the typo, my IDE said I can't use named arguments with non-Kotlin functions, so I extracted the values to variables and everything started working as it should.

 val expected = 42
 val actual = foo()
 assertEquals(expected, actual)
Kotta answered 6/8, 2018 at 17:14 Comment(0)
I
0

This seems to work also.

fun main(args: Array<String>) {

    var numberAdder : NumberAdder = NumberAdder(10, 20)
    var result : Int? = numberAdder.add()
    println("$result")
}

class NumberAdder (num1 : Int?, num2 : Int?) {

    var first : Int?
    var second : Int?

    init{
        first = num1
        second = num2
    }

fun add() : Int?{

    if(first != null && second != null){
        return first as Int + second as Int
    }

    if(first == null){
        return second
    }

    if(second == null){
        return first
    }

    return null
}

}
Interstadial answered 30/5, 2017 at 19:28 Comment(2)
This compiles, but it is (theoretically) unsafe. If some other thread were to change first or second after the if-test, but before either the casts or the addition, an exception will be thrown. I would go with one of the safe options in either mine or voddan's answer.Summerville
Yes, threading is another issue. But from compilation perspective I think error may due to reason that compiler was unable to decide whose plus method it needs to call in case of null. As Double, Int, Float all have plus method and also these are child classes of Number.Interstadial
P
-1
class NumberAdder (num1 : Int?, num2 : Int?) {

var first : Int? = null
var second : Int? = null

init{
    first = num1
    second = num2
}

fun add() : Int?{

    if(first != null && second != null){
        **return first!!.toInt() + second!!.toInt()**

    }

    if(first == null){
        return second
    }

    if(second == null){
        return first
    }

    return null
}

}

  • it is working but i don't know ?
Preternatural answered 8/2, 2023 at 16:25 Comment(2)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Palmer
Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. Would you kindly edit your answer to include additional details for the benefit of the community?Lashandralashar

© 2022 - 2024 — McMap. All rights reserved.