Scala Tutorial
Basics
Control Statements
OOP Concepts
Parameterized - Type
Exceptions
Scala Annotation
Methods
String
Scala Packages
Scala Trait
Collections
Scala Options
Miscellaneous Topics
In Scala, value classes are a mechanism to avoid allocating runtime objects, which can be particularly useful when you want to create rich domain primitives without incurring a performance cost. This feature is valuable because one of the best practices in domain-driven design is to avoid using primitive types directly but rather to wrap them in domain-specific types. However, creating a new object for every primitive wrapper can impose a runtime overhead. Value classes come to the rescue in such scenarios.
AnyVal
.val
or var
fields.def
s (methods), but it should not have other state.Here's an example of a value class:
class Meter(val value: Double) extends AnyVal { def +(other: Meter): Meter = new Meter(value + other.value) } val m1 = new Meter(5.0) val m2 = new Meter(3.0) val m3 = m1 + m2 println(m3.value) // 8.0
Any
with only abstract methods).null
.Under the hood, the Scala compiler tries to use the underlying primitive representation at runtime whenever possible, avoiding unnecessary object creation. In our example above, Meter
instances are typically represented as Double
values at runtime.
However, in certain situations, the compiler might still need to box the value class into an object, such as:
Any
reference on the value class.Value classes in Scala provide a means to create lightweight wrapper types around primitives (or references) without the usual object allocation overhead. They are useful for creating more meaningful domain types, enforcing type safety, and providing domain-specific operations without sacrificing performance.
Benefits of using value classes in Scala:
case class Meters(value: Double) extends AnyVal { def toFeet: Double = value * 3.28084 }
When to use value classes in Scala:
class Temperature(val value: Double) extends AnyVal { def toCelsius: Double = (value - 32) * 5 / 9 }
Defining and using value classes in Scala:
extends AnyVal
syntax. They should have a single parameter in their primary constructor.class UserName(val value: String) extends AnyVal val user: UserName = new UserName("JohnDoe")
Limitations of value classes in Scala:
// This will not compile due to the limitation on the number of parameters class InvalidValueClass(val value1: Int, val value2: Int) extends AnyVal
Comparing value classes with case classes in Scala:
case class Point(x: Double, y: Double) class PointValue(val x: Double, val y: Double) extends AnyVal
Implicit conversions and value classes in Scala:
implicit def doubleToTemperature(value: Double): Temperature = new Temperature(value) val temp: Temperature = 32.0