Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
836 views
in Technique[技术] by (71.8m points)

scala - Should implicit classes always extend AnyVal?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...