Можно ли получить доступ к функциям расширения из кода 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();
Однако это не работает. Среда не распознает bar()
метод, и компиляция не удалась.
Что работает, использует статическую функцию из kotlin:
public fun bar(): Int {
return 2*2
}
с помощью import com.test.extensions.ExtensionsPackage
так мой IDE , кажется, настроен правильно.
Я искал весь файл взаимодействия с Java из документации kotlin, а также много гуглил, но не смог его найти.
Что я делаю не так? Это вообще возможно?
java
kotlin
extension-function
Lovis
источник
источник
import package com.test.extensions.MyModel
?com.test.extensions.ExtensionsPackage
Ответы:
Все функции Kotlin, объявленные в файле, будут по умолчанию скомпилированы в статические методы в классе в том же пакете и с именем, полученным из исходного файла Kotlin ( заглавная буква и расширение ".kt" заменены суффиксом "Kt" ) , Методы, сгенерированные для функций расширения, будут иметь дополнительный первый параметр с типом получателя функции расширения.
Применяя его к исходному вопросу, компилятор Java увидит исходный файл Kotlin с именем example.kt
как если бы был объявлен следующий класс Java
Поскольку с расширенным классом с точки зрения Java ничего не происходит, вы не можете просто использовать точечный синтаксис для доступа к таким методам. Но они по-прежнему могут вызываться как обычные статические методы Java:
Статический импорт может быть использован для класса ExampleKt:
источник
bar(model, param1, param2);
Функция расширения верхнего уровня Kotlin скомпилирована как статические методы Java.
Данный файл Kotlin
Extensions.kt
в упаковке,foo.bar
содержащей:Эквивалентный Java-код будет:
Если только
Extensions.kt
в строке не содержитсяВ этом случае статический класс Java будет назван
DemoUtils
В Kotlin методы расширения могут быть объявлены другими способами. (Например, как функция-член или как расширение объекта-компаньона.)
источник
У меня есть файл Kotlin с именем NumberFormatting.kt, который имеет следующую функцию
В Java я просто получить доступ к нему через файл NumberFormattingKt следующим образом после необходимого импорта
import ....extensions.NumberFormattingKt;
источник
Вы всегда можете увидеть фактический код Java, который генерируется из вашего кода Kotlin, перейдя по ссылке
Tools > Kotlin > Show Kotlin Bytecode
, затем нажавDecompile
. Это может вам очень помочь. В вашем случае код Java будет выглядеть так, если у вас естьMyModelExtensions.kt
Вы можете улучшить это, используя
@JvmName
файл, содержащийbar
:и это приведет к следующему коду:
Использование
MyModels
соответствует тому, что Effective Java предлагает для служебных классов. Вы также можете переименовать ваш метод следующим образом:тогда со стороны Java это будет выглядеть идиоматично:
источник
Вам нужно продублировать ваши функции в файлах классов:
Создать файл Kotlin, например, для Utils.kt
введите код
ИЛИ
В котлине используют:
В Java используйте это:
источник
Меня устраивает:
Котлин
Java-код
Мой проект - старый проект Android, созданный на Java; Теперь я создал первый файл kotlin и добавил забавные расширения String. String.isNotNullOrEmpty (): Boolean {...}
и я мог бы вызвать его из файла Java, используя: StringUtilsKt.isNotNullOrEmpty (thestring).
Мой котлин файл называется StringUtils
источник
Другие ответы здесь покрывают случай вызова функции расширения, расположенной на верхнем уровне файла пакета Kotlin.
Однако в моем случае мне нужно было вызвать функцию Extension, расположенную внутри класса. В частности, я имел дело с Объектом.
Решение невероятно простое .
Все, что вам нужно сделать, это аннотировать вашу функцию расширения как
@JvmStatic
, и вуаля! Ваш Java-код сможет получить к нему доступ и использовать его.источник
Когда вы расширяете класс, как это:
Это скомпилируется в это:
Здесь есть еще примеры .
источник
Насколько я могу сказать, это невозможно. Из моего прочтения документации по расширениям видно, что
создает новый метод с подписью
Затем Kotlin отображает эту функцию на вызовы формы
myModel.bar()
, где, еслиbar()
не найден вMyModel
классе, он ищет статические методы, соответствующие схеме подписи и именования, которую он выводит. Обратите внимание, что это всего лишь предположение из их утверждений о том, что расширения статически импортируются и не переопределяют определенные методы. Я не зашел достаточно далеко в их источнике, чтобы знать наверняка.Таким образом, если предположить, что вышеприведенное верно, то нет никакого способа вызвать расширения Kotlin из простого старого Java-кода, так как компилятор просто увидит, что неизвестный метод вызывается для объекта, и выдает ошибку.
источник