隐式值类中的继承是否引入了开销



我想将 scala 的值类应用于我的一个项目,因为它们使我能够在没有大量开销的情况下丰富某些基元类型(我希望(并保持类型安全。

object Position {
  implicit class Pos( val i: Int ) extends AnyVal with Ordered[Pos] {
    def +( p: Pos ): Pos = i + p.i
    def -( p: Pos ): Pos = if ( i - p.i < 0 ) 0 else i - p.i
    def compare( p: Pos ): Int = i - p.i
  }
}

的问题:每当我使用Pos对象时,Ordered的继承是否会强制分配它们(从而引入很大的开销(?如果是这样:有没有办法规避这一点?

每次Pos都被视为Ordered[Pos],分配就会发生。有几种情况必须进行分配,请参阅 http://docs.scala-lang.org/overviews/core/value-classes.html#when_allocation_is_necessary。

因此,当执行诸如调用<这样简单的事情时,您将获得分配:

val x = Pos( 1 )
val y = Pos( 2 )
x < y // x & y promoted to an actual instance (allocation)

相关规则是(引自上述文章(:

每当将值类视为另一种类型(包括通用特征(时,必须实例化实际值类的实例 和: 此规则的另一个实例是将值类用作类型参数时。

反汇编上面的代码片段证实了这一点:

 0: aload_0
 1: iconst_1
 2: invokevirtual #21                 // Method Pos:(I)I
 5: istore_1
 6: aload_0
 7: iconst_2
 8: invokevirtual #21                 // Method Pos:(I)I
11: istore_2
12: new           #23                 // class test/Position$Pos
15: dup
16: iload_1
17: invokespecial #26                 // Method test/Position$Pos."<init>":(I)V
20: new           #23                 // class test/Position$Pos
23: dup
24: iload_2
25: invokespecial #26                 // Method test/Position$Pos."<init>":(I)V
28: invokeinterface #32,  2           // InterfaceMethod scala/math/Ordered.$less:(Ljava/lang/Object;)Z

可以看出,我们确实有两个用于类Position$Pos的"新"操作码实例

UPDATE:为了避免在这样的简单情况下进行分配,您可以手动覆盖每个方法(即使它们只转发到原始实现(:

override def <  (that: Pos): Boolean = super.<(that)
override def >  (that: Pos): Boolean = super.>(that)
override def <= (that: Pos): Boolean = super.<=(that)
override def >= (that: Pos): Boolean = super.>=(that)

这将在按示例执行x < y时删除分配。但是,这仍然保留了将Pos视为Ordered[Pos]的情况(例如,当传递给采用 T 作为类型参数的Ordered[Pos]Ordered[T]的方法时(。在这种特殊情况下,您仍然会获得分配,并且没有办法解决这个问题。

相关内容

  • 没有找到相关文章

最新更新