Should implicit classes always extend AnyVal?

ScalaImplicit Conversion

Scala Problem Overview


Say I'm writing an extension method

implicit class EnhancedFoo(foo: Foo) {
  def bar() { /* ... */ }
}

Should you always include extends AnyVal in the class defininition? Under what circumstances would you not want to make an implicit class a value class?

Scala Solutions


Solution 1 - Scala

Let's look at the limitations listed for value classes and think when they may not be suitable for implicit classes:

  1. "must have only a primary constructor with exactly one public, val parameter whose type is not a value class." So if the class you are wrapping is itself a value class, you can't use an implicit class as a wrapper, but you can do this:

     // wrapped class
     class Meters(val value: Int) extends AnyVal { ... }
    
     // wrapper
     class RichMeters(val value: Int) extends AnyVal { ... }
     
     object RichMeters { 
       implicit def wrap(m: Meter) = new RichMeter(m.value)
     }
    

    If your wrapper has implicit parameters as well, you can try to move them to the method declarations. I.e. instead of

     implicit class RichFoo[T](foo: Foo[T])(implicit ord: Ordering[T]) {
       def bar(otherFoo: Foo[T]) = // something using ord
     }
    

    you have

     implicit class RichFoo[T](foo: Foo[T]) extends AnyVal {
       def bar(otherFoo: Foo[T])(implicit ord: Ordering[T]) = // something using ord
     }
    
  2. "may not have specialized type parameters." You may want the wrapper to be specialized when wrapping a class which itself has specialized type parameters.

  3. "may not have nested or local classes, traits, or objects" Again, something which may well be useful for implementing a wrapper.

  4. "may not define a equals or hashCode method." Irrelevant, since implicit classes also shouldn't have equals/hashCode.

  5. "must be a top-level class or a member of a statically accessible object" This is also where you'd normally define implicit classes, but not required.

  6. "can only have defs as members. In particular, it cannot have lazy vals, vars, or vals as members." Implicit classes can have all of those, though I can't think of a sensible usecase for vars or lazy vals.

  7. "cannot be extended by another class." Again, implicit classes can be extended, but there is probably no good reason to.

In addition, making your implicit class a value class could possibly change some behavior of code using reflection, but reflection shouldn't normally see implicit classes.

If your implicit class does satisfy all of those limitations, I can't think of a reason not to make it a value class.

Solution 2 - Scala

I sense you're confusing Value Classes with Implicit Classes. You'd rarely extend anything when defining an Implicit Class for an enhancement while Value Classes must extend AnyVal.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLuigi PlingeView Question on Stackoverflow
Solution 1 - ScalaAlexey RomanovView Answer on Stackoverflow
Solution 2 - ScalaRandall SchulzView Answer on Stackoverflow