Intereting Posts

Доступ к функциям расширения Kotlin из Java

Можно ли получить доступ к функциям расширения из кода Java?

Я определил функцию расширения в файле Kotlin.

package com.test.extensions import com.test.model.MyModel /** * */ public fun MyModel.bar(): Int { return this.name.length() } 

Где MyModel является (сгенерированным) классом java. Теперь я хотел получить к нему доступ в своем обычном Java-коде:

 MyModel model = new MyModel(); model.bar(); 

Однако это не работает. IDE не распознает метод bar() и компиляция завершится неудачно.

Что работает с статической функцией от kotlin:

 public fun bar(): Int { return 2*2 } 

используя import com.test.extensions.ExtensionsPackage поэтому моя IDE настроена правильно.

Я просматривал весь файл Java-interop из документов kotlin, а также много искал в googled, но я не мог его найти.

Что я делаю не так? Возможно ли это?

Solutions Collecting From Web of "Доступ к функциям расширения Kotlin из Java"

Все функции Kotlin, объявленные в файле, будут по умолчанию ставить статические методы в классе внутри одного и того же пакета и с именем, полученным из исходного файла Kotlin (буква с буквой в буквах и расширение «.kt» заменено суффиксом «Kt» ) , Методы, сгенерированные для функций расширения, будут иметь дополнительный первый параметр с типом приемника функции расширения.

Применяя его к исходному вопросу, Java-компилятор увидит исходный файл Kotlin с именем example.kt

 package com.test.extensions public fun MyModel.bar(): Int { /* actual code */ } 

как если бы был объявлен следующий класс Java

 package com.test.extensions class ExampleKt { public static int bar(MyModel receiver) { /* actual code */ } } 

Поскольку ничего не происходит с расширенным классом с точки зрения Java, вы не можете просто использовать точечный синтаксис для доступа к таким методам. Но они по-прежнему можно назвать обычными статическими методами Java:

 import com.test.extensions.ExampleKt; MyModel model = new MyModel(); ExampleKt.bar(model); 

Статический импорт может использоваться для класса ExampleKt:

 import static com.test.extensions.ExampleKt.*; MyModel model = new MyModel(); bar(model); 

Функция расширения верхнего уровня Kotlin скомпилирована как статические методы Java.

Учитывая файл Kotlin Extensions.kt в пакете foo.bar содержащий:

 fun String.bar(): Int { ... } 

Эквивалентным Java-кодом будет:

 package foo.bar; class ExtensionsKt { public static int bar(String receiver) { ... } } 

Если, кроме того, Extensions.kt содержал строку

 @file:JvmName("DemoUtils") 

В этом случае статический класс Java будет называться DemoUtils

В Котлине методы расширения могут быть объявлены другими способами. (Например, как функция-член или как расширение объекта-компаньона.) Я попытаюсь расширить этот ответ позже.

Насколько я могу судить, это невозможно. Из моего чтения документов расширений, кажется, что

 public fun MyModel.bar(): Int { return this.name.length() } 

создает новый метод с подписями

 public static int MyModelBar(MyModel obj) { return obj.name.length(); } 

Затем Kotlin сопоставляет эту функцию с вызовами формы myModel.bar() , где, если bar() не найден в классе MyModel он ищет статические методы, соответствующие схеме сигнатуры и именования, которую он выводит. Обратите внимание, что это всего лишь предположение из их утверждений о том, что расширения, статически импортированные и не переопределяющие определенные методы. Я не получил достаточно далеко от их источника, чтобы точно знать.

Итак, если предположить, что это верно, нет никаких причин, чтобы расширения Kotlin вызывались из простого старого java-кода, поскольку компилятор просто увидит неизвестный метод, вызываемый на объект и ошибку.

Другие ответы здесь касаются случая вызова функции расширения, расположенной на верхнем уровне файла пакета Kotlin.

Однако в моем случае я должен был назвать функцию расширения, расположенную внутри класса. В частности, я имел дело с Объектом.

Решение невероятно просто .

Все, что вам нужно сделать, это аннотировать вашу функцию расширения как @JvmStatic и вуаля! Ваш Java-код сможет получить к нему доступ и использовать его.

Вам нужно дублировать свои функции в файлах классов:

Создайте файл Kotlin для ex Utils.kt

введите код

  class Utils { companion object { @JvmStatic fun String.getLength(): Int {//duplicate of func for java return this.length } } } fun String.getLength(): Int {//kotlin extension function return this.length } 

ИЛИ

 class Utils { companion object { @JvmStatic fun getLength(s: String): Int {//init func for java return s.length } } } fun String.getLength(): Int {//kotlin extension function return Utils.Companion.getLength(this)//calling java extension function in Companion } 

В kotlin использовать:

 val str = "" val lenth = str.getLength() 

В Java используйте это:

 String str = ""; Integer lenth = Utils.getLength(str);