价值类别、普遍特征和实例化的必要性



在值类的规范中,它说:

值类只能扩展通用特征,不能自己扩展。通用特征是扩展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

第一个问题

现在,我认为这意味着以下(可能)不需要实例化:

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)

这些会导致实例化吗?

我说得对吗?

不,如果我们用-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的类型签名,所以我们在这里自食其果,因为我们有效地"将值类ttpe视为另一种类型"。

尽管调用被分派到静态方法调用:

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)

现在,这对您的两个示例都有效,因为不需要在创建的接口上进行任何动态调度。

相关内容

  • 没有找到相关文章

最新更新