ПрограммированиеBackend разработчик

Что такое 'inline class' (value class) в Kotlin? Для чего они нужны, как правильно их использовать, какие ограничения и особенности есть у таких классов? Приведите примеры кода.

Проходите собеседования с ИИ помощником Hintsage

Ответ

inline class (с Kotlin 1.5 — value class) позволяет создавать обертки над примитивами без создания отдельного объекта во время выполнения. Это используется для повышения type-safety без издержек на аллокацию памяти. Под капотом такие объекты могут компилироваться в соответствующий примитив.

Пример:

@JvmInline value class UserId(val id: String) fun printUserId(userId: UserId) { println(userId.id) }
  • Только одно свойство (основное поле) разрешено.
  • Без-аргументный конструктор невозможен.
  • Класс не может содержать состояние (например, var-поля), только val.
  • Нельзя наследовать другие классы, но можно реализовывать интерфейсы.
  • Взаимодействие с java-кодом может быть неочевидным — возможна boxing/unboxing.

Использование inline/value классов важно для типизации идентификаторов, денег, единиц измерения и т.д.

Вопрос с подвохом

Может ли value class иметь больше одного свойства?

Ответ: Нет. Value class может содержать только одно property в primary constructor.

Пример ошибочного кода:

@JvmInline value class Money(val amount: Int, val currency: String) // Ошибка компиляции

Примеры реальных ошибок из-за незнания тонкостей темы


История

В обменнике валют применяли inline class для описания суммы и валюты. Попытались добавить два поля в value class, получили ошибку компиляции и тратили некоторое время на попытку обойти ограничение. В итоге решили сделать отдельную data class.


История

При интеграции с внешней Java-библиотекой inline class иногда преобразовывался в объект (boxing) неожиданно, что повлияло на производительность. После анализа документации заменили на обычный value object.


История

На проекте с микросервисами использовали value class как id-шники в API. Один из сервисов возвращал строку напрямую, другой — value class, что привело к сериализационному конфликту с Jackson. Исправили путем явного маппинга между id и строкой.