5.17. Klasy wartości

Klasy rozszerzające AnyVal są zwane klasami wartości. Przykładem takiej klasy jest ValueClass1.

Plik ValueClass1.scala:
class ValueClass1(val value: Int) extends AnyVal

Instancje takich klas nie są reprezentowane na maszynie wirtualnej jako osobne obiekty. Przykładowo, kompilator w przypadku obu metod (add1 i add2) z klasy Add generuje kod bajtowy działający na prymitywnych wartościach całkowitych, mimo że na poziomie języka ta pierwsza obsługuje wartości typu Int, a ta druga wartości typu ValueClass1.

Plik Add.scala:
class Add {
  def inc1(x: Int) = x+1
  def inc2(x: ValueClass1) = new ValueClass1(x.value+1)
}

Klasy wartości podlegają różnym ograniczeniom. Muszą mieć dokładnie jeden parametr będący wartością zadeklarowaną z przedostkiem val, nie mogą definiować żadnych pól składowych, ani dodatkowych konstruktorów.

scala> class ValueClass2(value:Int) extends AnyVal
<console>:10: error: value class parameter must be a val and not be private[this]
       class ValueClass2(value:Int) extends AnyVal
                         ^

scala> class ValueClass3(val value:Int) extends AnyVal { val value2:Double=1 }
<console>:10: error: field definition is not allowed in value class
       class ValueClass3(val value:Int) extends AnyVal { val value2:Double=1 }
                                                             ^

scala> class ValueClass4(val value:Int) extends AnyVal { def this()=this(0) }
<console>:10: error: secondary constructor is not allowed in value class
       class ValueClass4(val value:Int) extends AnyVal { def this()=this(0) }
                                                             ^

W pliku Decimal.scala zdefiniowana jest klasa wartości Decimal reprezentująca liczby mające dwie cyfry po przecinku.

Plik Decimal.scala:
class Decimal(val value:Int) extends AnyVal {
  def +(x:Decimal) = new Decimal(value+x.value)
  def -(x:Decimal) = new Decimal(value-x.value)
  def *(x:Decimal) = new Decimal(value*x.value/100)
  def toInt = value/100
  def toDouble = value.toDouble/100
  override def toString = f"${value/100}.${value.abs%100}%02d"
}

Wartość value jest liczbą całkowitą typu Int, sto razy większą od wartości reprezentowanej przez instancję klasy. Również tworząc instancje tej klasy należy jako argument konstruktora podać wartość całkowitą sto razy większą.

scala> val a = new Decimal(515)
a: Decimal = 5.15

scala> val b = new Decimal(-314)
b: Decimal = -3.14

Poniższe wyrażenia prezentują przykłady wykorzystania wartości typu Decimal.

scala> a+b
res0: Decimal = 2.01

scala> a-b
res1: Decimal = 8.29

scala> a*b
res2: Decimal = -16.17
scala> a.toInt
res3: Int = 5

scala> a.toDouble
res4: Double = 5.15

Specyfikacja języka Scala opisuje klasy wartości w punkcie 12.2.

Język programowania Scala Wydanie 2. Copyright © Grzegorz Balcerek 2016

Licencja Creative Commons

Ten utwór jest dostępny na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowe.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.