值类、普适性与实例化的必要性
Value classes, universal traits and the necessity of instantiation
在 specification of value classes 中,它说:
A value class can only extend universal traits and cannot be extended itself. A universal trait is a trait that extends Any
, only has def
s as members, and does no initialization. Universal traits allow basic inheritance of methods for value classes, but they incur the overhead of allocation. For example
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
第一个问题
现在,我认为这意味着以下(可能)不需要实例化:
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
我说得对吗?
第二个问题
而且我认为关于这是否需要实例化的机会均等:
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
在概率的平衡上,我也认为不需要实例化 - 我是对的吗?
编辑
我没有考虑示例中 print()
的确切实现:
def print(): Unit = println(this)
假设我改用了以下内容:
def print(): Unit = println(underlying)
这些会导致实例化吗?
Am I correct?
不,如果我们使用 -Xprint:jvm
:
发出最终编译输出,我们就可以看到它
<synthetic> object F$Wrapper extends Object {
final def print$extension($this: Int): Unit =
scala.Predef.println(new com.testing.F$Wrapper($this));
这是因为 println
的类型签名需要 Any
,所以我们在这里搬起石头砸自己的脚,因为我们实际上是 "treating the value class ttpe as another type"。
虽然调用被分派到静态方法调用:
val w: Int = 3;
F$Wrapper.print$extension(w)
我们仍在 print$extension
内进行分配。
如果我们偏离使用 Wrapper.this
,那么您的第一个假设确实是正确的,我们可以看到编译器愉快地展开 Wrapper
:
<synthetic> object F$Wrapper extends Object {
final def print$extension($this: Int): Unit =
scala.Predef.println(scala.Int.box($this));
现在调用站点如下所示:
val w: Int = 3;
com.testing.F$Wrapper.print$extension(w)
现在这对您的两个示例都有效,因为创建的界面上不需要任何动态调度。
在 specification of value classes 中,它说:
A value class can only extend universal traits and cannot be extended itself. A universal trait is a trait that extends
Any
, only hasdef
s as members, and does no initialization. Universal traits allow basic inheritance of methods for value classes, but they incur the overhead of allocation. For example
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
第一个问题
现在,我认为这意味着以下(可能)不需要实例化:
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
我说得对吗?
第二个问题
而且我认为关于这是否需要实例化的机会均等:
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
在概率的平衡上,我也认为不需要实例化 - 我是对的吗?
编辑
我没有考虑示例中 print()
的确切实现:
def print(): Unit = println(this)
假设我改用了以下内容:
def print(): Unit = println(underlying)
这些会导致实例化吗?
Am I correct?
不,如果我们使用 -Xprint:jvm
:
<synthetic> object F$Wrapper extends Object {
final def print$extension($this: Int): Unit =
scala.Predef.println(new com.testing.F$Wrapper($this));
这是因为 println
的类型签名需要 Any
,所以我们在这里搬起石头砸自己的脚,因为我们实际上是 "treating the value class ttpe as another type"。
虽然调用被分派到静态方法调用:
val w: Int = 3;
F$Wrapper.print$extension(w)
我们仍在 print$extension
内进行分配。
如果我们偏离使用 Wrapper.this
,那么您的第一个假设确实是正确的,我们可以看到编译器愉快地展开 Wrapper
:
<synthetic> object F$Wrapper extends Object {
final def print$extension($this: Int): Unit =
scala.Predef.println(scala.Int.box($this));
现在调用站点如下所示:
val w: Int = 3;
com.testing.F$Wrapper.print$extension(w)
现在这对您的两个示例都有效,因为创建的界面上不需要任何动态调度。