Класс Utils в Котлине

В 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. Допускается только прямое использование функции foo() (без префикса Utils).


Итак, как лучше всего объявить класс utils в Котлине?

Этот вопрос становится известным, я опубликовал для него статью здесь

nhoxbypass 05.05.2020 11:33
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
39
1
15 217
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

В Котлине:

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

val test = Utils.foo()

В Java:

final boolean test = Utils.foo()

Спасибо, может быть, стиль Java (UtilsClass.utilsFunc()) не так хорош с Kotlin, потому что часть UtilsClass избыточна, верно?

nhoxbypass 13.08.2018 05:05

Что ж, тут вопрос вкуса / стиля. Как указал @ zsmb13, вы можете получить этот синтаксис в Java с помощью @JvmName и использовать объявление верхнего уровня в Kotlin. Некоторые люди по-прежнему предпочитают именованный объект даже в Kotlin, поскольку он обеспечивает более согласованный стиль в многоязычном проекте.

marianosimone 13.08.2018 07:56

Я один из тех, кто все еще предпочитает названный объект даже в Котлине. xD

nhoxbypass 13.08.2018 08:36

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

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

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

Я знаком со стилем Java (UtilsClass.utilsFunc()), который объединяет функции с относительным значением в один и тот же класс (для простоты управления). Но в Котлине это не лучший подход, правда?

nhoxbypass 13.08.2018 05:10

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

Roland 13.08.2018 08:00
Ответ принят как подходящий

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

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

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


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

Дополнительная информация из ответа @Roland: использование object для утилит в Kotlin не имеет никакого смысла. Это не синглтон, правда? Спасибо вам всем\

nhoxbypass 13.08.2018 05:03

Другие вопросы по теме