Класс значений 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