Passing lambda instead of interface

前端 未结 5 1806
执念已碎
执念已碎 2020-12-08 12:44

I have created an interface:

interface ProgressListener {
    fun transferred(bytesUploaded: Long)
}

but can use it only as an anonymous clas

5条回答
  •  暖寄归人
    2020-12-08 13:24

    Kotlin 1.4 and after

    Kotlin 1.4 will fix this problem via "Functional Interfaces"

    Kotlin Functional Interface

    • Kotlin API: Perfect
    • Kotlin Access: Perfect
    • Java Access: Perfect
    class KotlinApi {
        fun interface Listener {
            fun onResponse(response: String)
        }
    
        fun demo(listener: Listener) {
            listener.onResponse("response")
        }
    }
    
    fun kotlinConsumer() {
        KotlinApi().demo { response ->
            println(response)
        }
    }
    
    public static void javaConsumer(){
        new KotlinApi().demo(response -> {
            System.out.println(response);
        });
    }
    

    Before Kotlin 1.4

    There is no single ultimate solution for this problem if you are aiming best access experience from both Kotlin and Java.

    If Kotlin developers had not thought SAM conversion for Kotlin interfaces is unnecessary, "Kotlin Interface" method would be ultimate solution.

    https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
    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.

    Select the best solution for your use case.

    Kotlin Function Type

    • Kotlin API: Perfect
    • Kotlin Access: Perfect
    • Java Access:
      • Auto generated parameter type like Function1 (not a big problem for Java 8 lambda)
      • Verbose return Unit.INSTANCE; instead of void return.
    class KotlinApi {
        fun demo(listener: (response: String) -> Unit) {
           listener("response")
        }
    }
    
    fun kotlinConsumer() {
        KotlinApi().demo { response->
            println(response)
        }
    }
    
    public static void javaConsumer() {
        new KotlinApi().demo(response -> {
            System.out.println(response);
            return Unit.INSTANCE;
        });
    }
    

    Kotlin Interface

    • Kotlin API: Additional interface definition.
    • Kotlin Access: Too verbose
    • Java Access: Perfect
    class KotlinApi {
        interface Listener {
            fun onResponse(response: String)
        }
    
        fun demo(listener: Listener) {
           listener.onResponse("response")
        }
    }
    
    fun kotlinConsumer() {
        KotlinApi().demo(object : KotlinApi.Listener {
            override fun onResponse(response: String) {
                println(response)
            }
        })
    }
    
    public static void javaConsumer() {
        new KotlinApi().demo(response -> {
            System.out.println(response);
        });
    }
    

    Java Interface

    • Kotlin API: Mixed Java code.
    • Kotlin Access: A little verbose
    • Java Access: Perfect
    class KotlinApi {
        fun demo(listener: Listener) {
            listener.onResponse("response")
        }
    }
    
    public interface Listener {
        void onResponse(String response);
    }
    
    fun kotlinConsumer() {
        KotlinApi().demo { response ->
            println(response)
        }
    }
    
    public static void javaConsumer() {
        new KotlinApi().demo(response -> {
            System.out.println(response);
        });
    }
    

    Multiple Methods

    • Kotlin API: Multiple method implementations
    • Kotlin Access: Perfect if correct method is used. Auto completion suggests verbose method also.
    • Java Access: Perfect. Auto completion does not suggest function type method because of JvmSynthetic annotation
    class KotlinApi {
        interface Listener {
            fun onResponse(response: String)
        }
    
        fun demo(listener: Listener) {
            demo { response ->
                listener.onResponse(response)
            }
        }
    
        @JvmSynthetic //Prevents JVM to use this method
        fun demo(listener: (String) -> Unit) {
            listener("response")
        }
    }
    
    fun kotlinConsumer() {
        KotlinApi().demo { response ->
            println(response)
        }
    }
    
    public static void javaConsumer() {
        new KotlinApi().demo(response -> {
            System.out.println(response);
        });
    }
    

    Java API

    • Kotlin API: There is no Kotlin API, all API code is Java
    • Kotlin access: Perfect
    • Java access: Perfect
    public class JavaApi {
        public void demo(Listener listener) {
            listener.onResponse("response");
        }
    
        public interface Listener {
            void onResponse(String response);
        }
    
    }
    
    fun kotlinConsumer() {
        JavaApi().demo { response ->
            println(response)
        }
    }
    
    public static void javaConsumer() {
        new JavaApi().demo(response -> {
            System.out.println(response);
        });
    }
    

提交回复
热议问题