Классы значений — это механизм в Scala, позволяющий избежать выделения объектов времени выполнения. Это достигается за счет определения новых подклассов AnyVal. Ниже показано очень минимальное определение класса значений:

case class UserId(id: Int) extends AnyVal

Как видно из приведенного выше раздела, чтобы класс был классом значений, он должен иметь ровно один параметр и внутри него не должно быть ничего кроме определений. Кроме того, никакой другой класс не может расширять класс значений, а класс значений не может переопределять equals или hashCode. Чтобы определить класс значения, сделайте его подклассом AnyVal и поместите ключевое слово val перед одним параметром. Вот как вы можете распознавать или создавать классы значений в Scala.

Потребность в классах значений?

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

Классы значений в основном используются для оптимизации производительности и оптимизации памяти. Вы можете думать, что многие из этих классов являются вашими типичными примитивами Scala, такими как классы Int, Boolean, Double и т. д. Вариант использования, где вы хотели бы и где вы могли бы применить классы значений, относится к крошечным типам. Давайте рассмотрим пару примеров того, как это можно применить.

В приведенном выше примере у нас есть очень простая модель данных, в которой есть пользователь и твит. Обратите внимание, что мы используем Int для двух типов, которые на самом деле не связаны между собой: идентификатор пользователя и идентификатор твитера совершенно разные, поэтому мы можем различать их. В остальном ничего особенного в приведенном выше коде нет.

Теперь, что произойдет, если я захочу использовать концепцию крошечных типов. Давайте рассмотрим еще один пример, где мы используем крошечные типы.

Теперь, что происходит, когда я использовал концепцию типов java, чтобы использовать более конкретные классы для идентификатора пользователя и имени пользователя, что означает, что теперь я не могу использовать любое число напрямую, и я не могу смешивать идентификатор твита с идентификатором пользователя, потому что компилятор помогает нам убедиться в этом. Вот почему мы создали здесь четыре класса, чтобы обернуть очень простые значения Int и String. Таким образом, User и Tweet напрямую принимают крошечные типы вместо значений Int или String.

Сгенерируем байт-код для User.scala командой:
javap -p User

public class User implements scala.Product,scala.Serializable { private final UserId id; private final Username name; ... }

Теперь, если вы посмотрите на байт-код, сгенерированный этим, как и следовало ожидать, и мы увидим, что у пользователя есть два поля, и эти поля имеют тип UserId и UserName, что означает, что каждый раз, когда я создаю пользователя, я также также создание экземпляров этих двух классов. Вот тут-то и появляются классы значений.

Давайте рассмотрим последний пример, где мы используем классы значений:

Что мы сделали в приведенном выше примере, так это то, что мы просто взяли эти крошечные типы и сделали их классами значений, расширив AnyVal. Они являются идеальными кандидатами, потому что все они обертывают одно простое значение. Итак, четыре класса, которые мы создали, мы просто превратили в классы Value. Но когда вы посмотрите на байт-код, сгенерированный на этот раз, вы поймете разницу.

public class User implements scala.Product,scala.Serializable { private final int id; private final java.lang.String name; ... }

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

Первоначально опубликовано на blog.knoldus.com 21 октября 2018 г.