11 декабря 2023
Тэги: Kotlin, ООП, руководство.
Иногда в процессе разработки на Kotlin требуется обеспечить более узкую типизацию параметров, чем позволяют стандартные типы. Особенно, если метод принимает несколько параметров одинакового типа, но каждый параметр несёт разный смысл.
Например, пусть у вас есть метод calculateDensity(), вычисляющий плотность вещества как массу, делённую на объём. Оба параметра передаём как тип Double:
Тогда вызов этого метода может выглядеть вот так:
Вроде всё тривиально, но без подсказок IDE довольно легко перепутать объём и плотность местами при вызове метода. И если такое произойдёт, компилятор вам никак не поможет.
Для повышения читаемости Kotlin позволяет указывать имена параметров при вызове метода. Однако и тут компилятор не различает массу и объём:
Первое, что приходит в голову – это создать отдельные классы Weight и Volume, но это может добавить накладные расходы во время выполнения, т.к. вместо примитивов мы используем уже более сложные объекты.
В Kotlin есть особое подмножество классов, называемых value class. Они сочетают в себе высокую производительность как у примитивов и некоторые преимущества ООП, как у обычных классов.
При объявлении таких классов мы используем модификатор value и обязательно добавляем аннотацию @JvmInline. Такой класс может содержать только одно поле, не может быть унаследован от другого класса и сам по себе является финальным. В остальном вы можете добавлять в этот класс методы, реализовать интерфейс и т.п.
Тогда наш метод calculateDensity() примет следующий вид:
В процессе компиляции обращения к полям этих value-классов будут заменены непосредственно на примитивы. Вызов метод перепишем более наглядно:
Теперь мы не сможем передавать в метод просто тип Double. Мы всегда будем явно указывать, какой смысл придаём тому или иному значению.
В собственных приложениях вы можете создать, например, обёртку над String под названием Password.
Технически пароль – это такая же строка, но его ни в коем случае нельзя перепутать с другой строкой и «засветить» где-то в логах.
Механизм value class используется и в стандартной библиотеке Kotlin. Например, беззнаковое целое UInt представлено как обёртка над стандартным целым числом Int.
Поэтому, если Вы согласны с тезисом «чем строже типизация – тем лучше», тогда смело используйте value-классы.
Kotlin, Java, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Linux, Hibernate, Collections, Stream API, многопоточность, файлы, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.