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, H2, Linux, Hibernate, Collections, Stream API, многопоточность, чат-боты, нейросети, файлы, devops, Docker, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.