Rex*_*err 13 scala enrich-my-library value-class
Scala 2.10引入了值类,您可以通过使类扩展来指定它们AnyVal
.值类有许多限制,但它们的一个巨大优点是它们允许扩展方法而没有创建新类的惩罚:除非需要装箱,例如将值类放在数组中,它只是旧类加上一组将类作为第一个参数的方法.从而,
implicit class Foo(val i: Int) extends AnyVal {
def +*(j: Int) = i + j*j
}
Run Code Online (Sandbox Code Playgroud)
解开一些不比写i + j*j
自己更贵的东西(一旦JVM内联方法调用).
不幸的是,SIP-15中描述值类的一个限制是
- C的基础类型可能不是值类.
如果你有一个值类,你可以开始,比如说,作为一种提供类型安全单位而不需要拳击开销的方法(除非你真的需要它):
class Meter(val meters: Double) extends AnyVal {
def centimeters = meters*100.0 // No longer type-safe
def +(m: Meter) = new Meter(meters+m.meters) // Only works with Meter!
}
Run Code Online (Sandbox Code Playgroud)
那么有没有办法在Meter
没有对象创建开销的情况下进行充实?SIP-15的限制防止了明显的限制
implicit class RichMeter(m: Meter) extends AnyVal { ... }
Run Code Online (Sandbox Code Playgroud)
做法.
Rex*_*err 14
为了扩展值类,您需要重新获得基础类型.由于值类需要可以访问它们的包装类型(val i
不仅仅是i
上面的),因此您始终可以执行此操作.您无法使用方便的快捷implicit class
方式,但仍可以手动添加隐式转换.所以,如果你想添加一个-
方法,Meter
你必须做类似的事情
class RichMeter(val meters: Double) extends AnyVal {
def -(m: Meter) = new Meter(meters - m.meters)
}
implicit def EnrichMeters(m: Meter) = new RichMeter(m.meters)
Run Code Online (Sandbox Code Playgroud)
另请注意,您可以(自由地)使用原始值类重新包装任何参数,因此如果它具有您依赖的功能(例如,它包装Long
但执行复杂的位混合),您可以只重写底层类.您尝试在任何需要的地方扩展的价值类.
(另请注意,除非你,否则你会收到警告import language.implicitConversions
.)
附录:在Scala 2.11+中,您可以val
私有; 对于完成此操作的情况,您将无法使用此技巧.
归档时间: |
|
查看次数: |
1079 次 |
最近记录: |