Статьи
Утилиты Telegram YouTube Отзывы

Value-классы

Видеогайд

11 декабря 2023

Тэги: Kotlin, ООП, руководство.

Содержание

  1. Описание задачи
  2. Особенности value-классов
  3. Сценарии использования

Иногда в процессе разработки на Kotlin требуется обеспечить более узкую типизацию параметров, чем позволяют стандартные типы. Особенно, если метод принимает несколько параметров одинакового типа, но каждый параметр несёт разный смысл.

Описание задачи

Например, пусть у вас есть метод calculateDensity(), вычисляющий плотность вещества как массу, делённую на объём. Оба параметра передаём как тип Double:

fun calculateDensity(weight: Double, volume: Double): Double =
    weight / volume

Тогда вызов этого метода может выглядеть вот так:

fun main() {
    val density = calculateDensity(3.0, 2.0)
    println("Density: $density.")
}

Вроде всё тривиально, но без подсказок IDE довольно легко перепутать объём и плотность местами при вызове метода. И если такое произойдёт, компилятор вам никак не поможет.

Для повышения читаемости Kotlin позволяет указывать имена параметров при вызове метода. Однако и тут компилятор не различает массу и объём:

val density = calculateDensity(
    weight = 3.0,
    volume = 2.0,
)

Первое, что приходит в голову – это создать отдельные классы Weight и Volume, но это может добавить накладные расходы во время выполнения, т.к. вместо примитивов мы используем уже более сложные объекты.

Особенности value-классов

В Kotlin есть особое подмножество классов, называемых value class. Они сочетают в себе высокую производительность как у примитивов и некоторые преимущества ООП, как у обычных классов.

@JvmInline
value class Weight(val w: Double)

@JvmInline
value class Volume(val v: Double)

При объявлении таких классов мы используем модификатор value и обязательно добавляем аннотацию @JvmInline. Такой класс может содержать только одно поле, не может быть унаследован от другого класса и сам по себе является финальным. В остальном вы можете добавлять в этот класс методы, реализовать интерфейс и т.п.

Value-класс в Kotlin

Тогда наш метод calculateDensity() примет следующий вид:

fun calculateDensity(weight: Weight, volume: Volume): Double =
    weight.w / volume.v

В процессе компиляции обращения к полям этих value-классов будут заменены непосредственно на примитивы. Вызов метод перепишем более наглядно:

val density = calculateDensity(
    Weight(3.0),
    Volume(2.0),
)

Теперь мы не сможем передавать в метод просто тип Double. Мы всегда будем явно указывать, какой смысл придаём тому или иному значению.

Сценарии использования

В собственных приложениях вы можете создать, например, обёртку над String под названием Password.

@JvmInline
value class Password(val p: String)

Технически пароль – это такая же строка, но его ни в коем случае нельзя перепутать с другой строкой и «засветить» где-то в логах.

Механизм value class используется и в стандартной библиотеке Kotlin. Например, беззнаковое целое UInt представлено как обёртка над стандартным целым числом Int.

Поэтому, если Вы согласны с тезисом «чем строже типизация – тем лучше», тогда смело используйте value-классы.



Комментарии

Добавить комментарий

×

devmark.ru