Утилиты класса в Котлине

В Java мы можем создать класс утилит следующим образом:

final class Utils {
    public static boolean foo() {
        return false;
    }
}

Но как это сделать в Котлине?


Я пытаюсь использовать функции внутри object:

object Utils {
    fun foo(): Boolean {
        return false
    }
}

Но при вызове этого метода из кода Java к нему нужно добавить INSTANCE. Пример: Utils.INSTANCE.foo().


Затем я изменяюсь, чтобы объявить ее как функцию верхнего уровня (без class или object):

@file:JvmName("Utils")
@file:JvmMultifileClass

fun foo(): Boolean {
    return true
}

Затем я могу вызвать Utils.foo() из кода Java. Но из кода Kotlin я получил Unresolved reference ошибку Unresolved reference компилятора. Это позволяет только напрямую использовать функцию foo() (без префикса Utils).


Итак, каков наилучший подход для объявления класса утилит в Котлине?

Ответ 1

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

Вы тоже @JvmName аннотацию @JvmName, что именно то, как вы должны сделать эти функции верхнего уровня легко вызываемыми для пользователей Java.

Обратите внимание, что вам нужно только @JvmMultifileClass если вы @JvmMultifileClass свои функции верхнего уровня в разных файлах, но все же хотите, чтобы они @JvmMultifileClass в том же файле класса (опять же, только для пользователей Java). Если у вас есть только один файл или вы даете разные имена для каждого файла, вам не нужна эта аннотация.


Если по какой-то причине вам нужен такой же синтаксис Utils.foo() как в Java, но и в Kotlin, решение с object а затем @JvmStatic каждого метода - это способ сделать это, как уже показано в этом ответе @marianosimone.

Ответ 2

Для этого вам нужно использовать @JvmStatic:

В Котлине:

object Utils {
    @JvmStatic
    fun foo(): Boolean = true
}

val test = Utils.foo()

В Java:

final boolean test = Utils.foo()

Ответ 3

Обратите внимание, что класс util, который вы использовали в Java, был единственным способом предоставления дополнительных функций там, для всего, что не принадлежало определенному типу или объекту. Использование object для этого в Котлин не имеет никакого смысла. Это не синглтон, верно?

Второй подход, о котором вы упоминали, скорее всего подходит для использования служебных функций. Внутренне такие функции переходят на статические, и, как вы можете видеть, они становятся статическими классами использования в Java, которые вы ищете, так как вы не можете иметь автономные функции в Java без класса или перечисления. Однако в самом Котлине они являются просто функциями.

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