【发布时间】:2013-02-02 11:27:40
【问题描述】:
假设我在写一个扩展方法
implicit class EnhancedFoo(foo: Foo) {
def bar() { /* ... */ }
}
您是否应该始终在类定义中包含extends AnyVal?什么情况下不想让隐式类成为值类?
【问题讨论】:
假设我在写一个扩展方法
implicit class EnhancedFoo(foo: Foo) {
def bar() { /* ... */ }
}
您是否应该始终在类定义中包含extends AnyVal?什么情况下不想让隐式类成为值类?
【问题讨论】:
让我们看看limitations listed for value classes,想想它们什么时候可能不适合隐式类:
“必须只有一个主构造函数,其中只有一个公共的 val 参数,其类型不是值类。”所以如果你包装的类本身就是一个值类,你不能使用implicit class作为包装器,但是你可以这样做:
// 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)
}
如果你的包装器也有隐式参数,你可以尝试将它们移到方法声明中。 IE。而不是
implicit class RichFoo[T](foo: Foo[T])(implicit ord: Ordering[T]) {
def bar(otherFoo: Foo[T]) = // something using ord
}
你有
implicit class RichFoo[T](foo: Foo[T]) extends AnyVal {
def bar(otherFoo: Foo[T])(implicit ord: Ordering[T]) = // something using ord
}
“可能没有专门的类型参数。”在包装本身具有专用类型参数的类时,您可能希望包装器是专用的。
equals 或hashCode 方法。”无关紧要,因为隐式类也不应该有equals/hashCode。vars 或lazy vals 的合理用例。此外,将隐式类设为值类可能会使用反射改变代码的某些行为,但反射通常不会看到隐式类。
如果您的隐式类确实满足所有这些限制,我想不出不将其设为值类的理由。
【讨论】:
lazy val 在implicit class 中的用例:gist.github.com/SethTisue/8977033。幸运的是,有一个简单的解决方法(也显示在要点中)。
extends AnyVal 的任何好处。也许 JVM 通过决定不创建它们来消除这些短期对象的开销。
我感觉您将Value Classes 与Implicit Classes 混淆了。在为增强定义隐式类时,您很少扩展任何东西,而值类必须扩展AnyVal。
【讨论】: