Как объявить Kotlin Lambda с типом возвращаемого значения 'void' для вызывающей стороны Java? - PullRequest
0 голосов
/ 06 декабря 2018

У меня есть библиотека, полностью написанная на Kotlin, включая ее публичный API.Теперь пользователь библиотеки использует Java, проблема в том, что Kotlin Lambdas с типом возврата Unit не скомпилированы для возврата типа void.В результате сторона Java всегда должна возвращать Unit.INSTANCE для методов, которые эффективны void.Можно ли этого как-то избежать?

Пример:

Kotlin Lambda

interface Foo{
  fun bar(x:(String)->Unit)
}

Java-вызов

public void call(){
   foo.bar(this::processString)
}

//the return type should rather be void instead of Unit
public Unit processString(String s){  
    return Unit.INSTANCE 
    // ^^ implementations should not be forced to return anything 
 }

Можно ли объявить лямбду Kotlin по-другому, чтобы компилятор генерировал тип возврата void?

см. Также Как объявить функцию Kotlin с типом возвращаемого значения 'void' для вызывающей стороны Java?

1 Ответ

0 голосов
/ 06 декабря 2018

У меня нет реального ответа на это, но я поделюсь тем, что я сделал в такой ситуации, когда мне нужно было получить доступ к такому коду Kotlin из Java (или что мне пришло в голову).

В основном это зависит от того, какую сторону вы действительно хотите коснуться / улучшить, просто чтобы получить то, что вам нужно.

Расширение кода Kotlin для поддержки эквивалентов Java:

interface Foo {
  fun bar(x : (String) -> Unit)

  /* the following is only here for Java */
  @JvmDefault // this requires that you add -Xjvm-default=enable to your compiler flags!
  fun bar(x:Consumer<String>) = bar(x::accept)
}

Это имеет некоторые недостатки:Consumer -метод также виден из Котлина и поэтому также может быть вызван оттуда.Само собой разумеется, что вам нужно дублировать все функции в интерфейсах, и, следовательно, все ваши Kotlin-интерфейсы становятся более раздутыми.Но: это работает с обеих сторон так, как вы ожидаете.Java вызывает Consumer -вариант, Kotlin вызывает (String) -> Unit -вариант ... надеюсь ;-) на самом деле просто демонстрирует некоторые вызовы:

// from Java:
..bar(s -> { System.out.println(s); })
// however, method references might not work that easily or not without a workaround...
..bar((Consumer<String>) System.out::println); // not nice... @JvmName("kotlinsBar") to the rescue? well... that will just get more and more ugly ;-)

// from Kotlin:
..bar(Consumer(::println)) // or: ..bar(Consumer { println(it) })
..bar(::println)           // or: ..bar { println(it) } // whatever you prefer...

С другой стороны, еще один вариант - добавить вспомогательные методыэто на самом деле облегчает вызов функций Kotlin из Java, например, что-то вроде следующего:

fun <T> `$`(consumer: Consumer<T>): (T) -> Unit = consumer::accept

Который, вероятно, никогда не будет вызываться из Kotlin (так как написание обратных ссылок в сочетании с $ уже достаточно громоздко) или если выне хотите раздувать ваш код Kotlin, просто добавьте такой метод в Java, где, однако, он не выглядит таким уж тонким:

static <T> Function1<T, Unit> $(Consumer<T> consumer) {
    return t -> {
        consumer.accept(t);
        return Unit.INSTANCE;
    };
}

Вызовы этих методов оба выглядят одинаково:

..bar($(s -> /* do something with s */)) // where bar(x : (String) -> Unit)

Для вещей, которые мне нужно было решить, я просто возвратил Unit.INSTANCE или null, но если бы у меня было больше методов для вызова, я бы, вероятно, выбрал второй ($(...)) подход.В лучшем случае мне нужно только один раз предоставить (сгенерировать? ;-)) эквиваленты и использовать их в нескольких проектах, в то время как предоставление default вариантов в интерфейсах только для Java, вероятно, потребует гораздо больше работы и может даже запутать некоторых людей..

Наконец: нет ... Я не знаю ни одного варианта, который позволял бы вам иметь что-то вроде void -функциональных интерфейсов (/ потребителей) из Unit -возвратных функциональных интерфейсов Kotlin.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...