tutorial porque pagina oficial documentación desde cero java kotlin kotlin-interop

java - porque - pagina oficial kotlin



¿Por qué tengo que devolver Unit.INSTANCE al implementar en Java una función de Kotlin que devuelve una Unidad? (2)

Si tengo una función de Kotlin

fun f(cb: (Int) -> Unit)

y quiero llamar a f desde Java, tengo que hacerlo así:

f(i -> { dosomething(); return Unit.INSTANCE; });

que se ve muy feo. ¿Por qué no puedo escribirlo como f(i -> dosomething()); , ya que Unit in Kotlin es equivalente a void en Java?


Yo uso este enfoque para Kotlin y Java. Los métodos de MyKotlinClass que verá en Java, en Kotlin verán ambos métodos (método de clase + función de extensión).

MyKotlinClass { //Method to use in Java, but not restricted to use in Kotlin. fun f(cb: Consumer<Int>) { //Java8 Consumer, or any custom with the same interface int i = getYourInt() cb.accept(i) } } //Extension for Kotlin. It will be used in Kotlin. fun MyKotlinClass.f(cb: (Int) -> Unit) { f(Consumer { cb(it) }) }


Unit en Kotlin es mayoritariamente equivalente a la void en Java, sin embargo, solo cuando las reglas de la JVM lo permiten.

Los tipos funcionales en Kotlin están representados por interfaces como:

public interface Function1<in P1, out R> : Function<R> { /** Invokes the function with the specified argument. */ public operator fun invoke(p1: P1): R }

Cuando declara (Int) -> Unit , desde el punto de vista de Java, esto es equivalente a la Function<Integer, Unit> . Por eso tienes que devolver un valor. Para solucionar este problema, en Java hay dos interfaces separadas, Consumer<T> y Function<T, R> para cuando no tiene / tiene un valor de retorno.

Los diseñadores de Kotlin decidieron renunciar a la duplicación de interfaces funcionales y, en cambio, confiar en el compilador "magic". Si declara un lambda en Kotlin, no tiene que devolver un valor porque el compilador insertará uno por usted.

Para hacer su vida un poco más fácil, puede escribir un método auxiliar que envuelva un Consumer<T> en una Function1<T, Unit> :

public class FunctionalUtils { public static <T> Function1<T, Unit> fromConsumer(Consumer<T> callable) { return t -> { callable.accept(t); return Unit.INSTANCE; }; } }

Uso:

f(fromConsumer(integer -> doSomething()));

Dato curioso: el manejo especial de Unit por el compilador Kotlin es la razón por la que puede escribir código como:

fun foo() { return Unit }

o

fun bar() = println("Hello World")

Ambos métodos han devuelto el tipo void en el bytecode generado, pero el compilador es lo suficientemente inteligente como para darse cuenta de eso y le permite usar declaraciones / expresiones de retorno de todos modos.