Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does having a private constructor on a value class negate the benefits of a value class?

I'm thinking of making a value class that has some guard on how it can be instantiated. For the sake of example, say I want a non-negative integer:

class NonNegInt private (val value: Int) extends AnyVal

object NonNegInt {
  def apply(value: Int): Try[NonNegInt] = Try {
    if (value >= 0) new NonNegInt(value) else throw new IllegalArgumentException("non-negative integers only!")
  }
}

My only worry is that the private constructor may make it impossible for the scala compiler to treat the NonNegInt as a primitive int. Is this true?

like image 525
2rs2ts Avatar asked Dec 14 '25 09:12

2rs2ts


1 Answers

If "treat as a primitive" here means "avoid allocation", then this indeed will not work, but not because of a private constructor.

As mentioned in Value Classes Guide

Another instance of this rule is when a value class is used as a type argument. For example, the actual Meter instance must be created for even a call to identity.

def identity[T](t: T): T = t
identity(Meter(5.0))

Basically, because identity[T] is parametrized, invoking it on a value type requires an allocation of an instance. Try[T] is the same situation: Try { ... } "block" is an invocation of a parametrized function Try.apply[T] with T being NonNegInt. This call will require an allocation of NonNegInt instance.

like image 93
Dima Avatar answered Dec 15 '25 23:12

Dima



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!