oxb*_*kes 6 scala value-class universal-trait
值类只能扩展通用特征,不能自己扩展.一个普遍的特点是延伸的特质
Any,只有defS作为成员,并不做任何初始化.通用特征允许值类的方法的基本继承,但它们会产生分配的开销.例如
trait Printable extends Any {
def print(): Unit = println(this)
}
class Wrapper(val underlying: Int) extends AnyVal with Printable
val w = new Wrapper(3)
w.print() // actually requires instantiating a Wrapper instance
Run Code Online (Sandbox Code Playgroud)
现在,我想借此意味着以下的(可能)不要求实例:
trait Marker extends Any
class Wrapper(val underlying: Int) extends AnyVal with Marker {
def print(): Unit = println(this) //unrelated to Marker
}
val w = new Wrapper(3)
w.print() //probably no instantiation as print is unrelated to Marker
Run Code Online (Sandbox Code Playgroud)
我对么?
而且我认为这是否需要实例化是偶然的:
trait Printable extends Any {
def print(): Unit //no implementation
}
class Wrapper(val underlying: Int) extends AnyVal with Printable {
override def print() = println(this) //moved impl to value class
}
val w = new Wrapper(3)
w.print() // possibly requires instantiation
Run Code Online (Sandbox Code Playgroud)
在概率平衡上,我也认为不需要实例化 - 我是否正确?
我没有想过print()示例中的确切实现:
def print(): Unit = println(this)
Run Code Online (Sandbox Code Playgroud)
假设我使用以下代码:
def print(): Unit = println(underlying)
Run Code Online (Sandbox Code Playgroud)
这会导致实例化吗?
我对么?
不,如果我们使用以下命令发出最终的编译输出,我们就可以看到它-Xprint:jvm:
<synthetic> object F$Wrapper extends Object {
final def print$extension($this: Int): Unit =
scala.Predef.println(new com.testing.F$Wrapper($this));
Run Code Online (Sandbox Code Playgroud)
这是因为事实上println有一个类型签名需要Any,所以我们在这里搬起石头砸自己的脚,因为我们实际上是“将值类 ttpe 视为另一种类型”。
虽然调用被分派到静态方法调用:
val w: Int = 3;
F$Wrapper.print$extension(w)
Run Code Online (Sandbox Code Playgroud)
我们仍然在内部进行分配print$extension。
如果我们偏离 using Wrapper.this,那么你的第一个假设确实是正确的,我们可以看到编译器愉快地解开Wrapper:
<synthetic> object F$Wrapper extends Object {
final def print$extension($this: Int): Unit =
scala.Predef.println(scala.Int.box($this));
Run Code Online (Sandbox Code Playgroud)
调用站点现在如下所示:
val w: Int = 3;
com.testing.F$Wrapper.print$extension(w)
Run Code Online (Sandbox Code Playgroud)
现在这对于您的两个示例都有效,因为不需要在创建的接口上进行任何动态分派。