15

I want to pass vararg from the buy function to the drive function but I get

a compile error:

required Array<T> found Array<out T>

code:

class Car

fun buy(vararg cars: Car) {
    drive(cars) //compile error
}

fun drive(cars: Array<Car>) {
    //...
}

5 Answers 5

38

The precise error is:

Type mismatch.
Required: Array<Car>
Found:    Array<out Car>

The problem is that when you have a vararg cars: Car function parameter, its type inside the function is Array<out Car>, which basically represents a read-only array of the arguments the function was called with - after all, it wouldn't really be a nice thing to start modifying the arguments you got as a vararg (function parameters in Kotlin are read-only vals, and this is something very similar).

But your drive function requires a regular Array<Car>, which of course is writable as well. So if you wish to keep these function signatures, you'll need to create a new array that contains everything from your read-only array. This can be created using the following syntax:

drive(arrayOf(*cars))

This calls the arrayOf function we usually create arrays with, which takes a vararg parameter, and uses the spread operator which is a way to pass in the elements of an array (which cars is, inside the buy function) as the vararg parameters (docs here).

While all this may sound complicated, it's actually a very efficient solution, as it just uses Array.copyOf under the hood in the bytecode.

Sign up to request clarification or add additional context in comments.

1 Comment

I think the other answer is more typical, that you would favory Array<out Car> as the parameter for the second function, not make a copy.
7

Another solution would be to change drive to fun drive(Array<out Car>) { ... }. This of course means that the cars inside drive cannot be modified but avoids the copying.

Comments

2
fun foo(vararg strings: String): Array<out String> {
    return strings
}

//  Define a var 
var yourVar: Array<out String> = foo("a", "b", "c")

// Use var in Java method `public void javaMethod(String... someParam)() {}`
javaMethod(*yourVar)

Comments

1
override fun checkMatch(vararg cards: SetsCard): Int {
    return if (isSet(*cards)) 16 else -2
}

private fun isSet(vararg cards: SetsCard) : Boolean {
    if (cards.size == 3) {
        return true
    }
    return false
}

Comments

-2

Essencially you need the vararg keywork before the variable name.

fun args(vararg cars: Car) {
   //use cars as an array 
}

1 Comment

even if you want to add it to the second function, this will not fix the compile error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.