Класс значений Scala, варианты использования

Я знаю value class в Scala встроенная операция во время компиляции.

может быть так

case class A(i: Int) extends AnyVal {
   def +(that: A) = A(this.i + that.i)
} 
A(1) + A(2) // After compile it equals to 1 + 2 

Но это не имеет большого значения для меня.

Это может повысить производительность, но,

призвание this.i + that.i не кажется намного медленнее i + i

Зачем нам value class в Scala и любые случаи использования???

3 ответа

Решение

Зачем вам заключать одно значение в дополнительный класс?

Один большой пример использования - безопасность типов. Допустим, у вас есть функция, которая может умножать деньги, вот так:

def multiply(factor: Int, amount: Int): Int = ???

Проблема в том, что было бы очень легко перепутать два аргумента и, следовательно, вызвать функцию неправильно. С помощью классов значений вы можете создать Money введите и переписать функцию следующим образом:

case class Money(amount: Int) extends AnyVal
def multiply(factor: Int, amount: Money): Money = ???

Теперь с вашим специальным Money типа, компилятор скажет вам, если вы попытаетесь передать аргументы в неправильном порядке.

Если бы это был не класс стоимости, люди могут сказать, что в некоторых случаях добавленная безопасность типов не стоит потери производительности. Однако с классами значений у вас нет накладных расходов времени выполнения (хотя есть ограничения: http://docs.scala-lang.org/overviews/core/value-classes.html).

Альтернативой для достижения той же цели являются помеченные (без накладных расходов) тегированные типы в scalaz: http://eed3si9n.com/learning-scalaz/Tagged+type.html

Обратите внимание, что, например, haskell использует newtype для той же идеи: https://wiki.haskell.org/Newtype

Давайте посмотрим, как работает Scala с классами значений (-print опция).

case class A(i: Int) extends AnyVal {
   def +(that: A) = A(this.i + that.i)
} 
A(1) + A(2)

переводится на:

final def +$extension($this: Int, that: Int): Int = $this.+(that)
...
A.+$extension(1, 2)

Как вы можете видеть, Scala избегает работать с классом A и просто добавляет Int в Int возврате Int, В то же время:

case class A(i: Int) {
   def +(that: A) = A(this.i + that.i)
} 
A(1) + A(2)

переводится на:

def +(that: A): A = new A(this.i().+(that.i()))
...
new A(1).+(new A(2))

Так что вычислить 1 + 2 вам нужно создать экземпляр класса A три раза.

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

Подробнее о классах значений здесь Value Classes

Другие вопросы по тегам