Kotlin lambda with Interface as an argument

2019-08-14 07:32发布

问题:

I'm a bit baffled by the Koltin lambdas and I wanted to know how to use it given the following snippet of code:

interface KotlinInterface {

    fun doStuff(str: String): String
}

And the function that requires this Interface to be passed as a parameter:

fun kotlinInterfaceAsArgument(kotlinInterface: KotlinInterface): String{

   return kotlinInterface.doStuff("This was passed to Kotlin Interface method")
}

fun main(args: Array<String>){

    val newString = kotlinInterfaceAsArgument({
      str -> str + " | It's here" //error here (type mismatch)
    })
}

However, the same logic but in Java compiles and runs as intended.

public class JavaClass {

   public String javaInterfaceAsArgument(JavaInterface javaInterface){

        String passedToInterfaceMethod = "This was passed to Java Interface method";
        return javaInterface.doStuff(passedToInterfaceMethod);
    }

   public interface JavaInterface {

        public String doStuff(String str);
    }
}

and

public class Main {

    public static void main(String[] args) {

        JavaClass javaClass = new JavaClass();
        String newValue = javaClass.javaInterfaceAsArgument(str -> str + " | It's here!");

        System.out.println(newValue);
    }
}

How can I utilize lambda in Kotlin in this case?

回答1:

SAM conversion (as of 1.1) only works with Java interfaces, not Kotlin ones.

Also note that this feature works only for Java interop; since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported.

You can some ways to fix your code in this answer.

Edit: I've realized this is an exact duplicate of the other question, as even the error is the same.



回答2:

The proper way in pure Kotlin is to use higher-order functions: https://kotlinlang.org/docs/reference/lambdas.html

With higher-order function you can pass function as argument in it.

If we talk about your example:

fun kotlinFunctionAsArgument(kotlinFunction: (String) -> String): String {
    return kotlinFunction("This was passed to Kotlin Function method")
}

fun main(args: Array<String>){
    val newString = kotlinFunctionAsArgument({
        str -> str + " | It's here" //there are no errors
    })
}