Scala编译器如何在trait中定义final val?

Scala编译器如何在trait中定义final val?,scala,scalac,scala-compiler,Scala,Scalac,Scala Compiler,我经常使用无私特质模式,我需要在特质中使用“昂贵”常量: 我希望在我的所有应用程序中都有这些值的一个实例,这可能需要计算几个步骤 然而,无私的特质模式导致以下设计: 我的羽毛 对象MyStuff扩展了MyStuff 显然,将常量放入对象中并在特征中使用它们会创建循环依赖关系。然而,将它们放在trait上,使得所有扩展trait的类都可以覆盖它们,因此它们肯定不是应用程序范围的单例 Scala编译器是否“足够聪明”使trait中的final VAL变为“旧java公共静态final” 类似于公

我经常使用无私特质模式,我需要在特质中使用“昂贵”常量: 我希望在我的所有应用程序中都有这些值的一个实例,这可能需要计算几个步骤

然而,无私的特质模式导致以下设计:

  • 我的羽毛
  • 对象MyStuff扩展了MyStuff
显然,将常量放入对象中并在特征中使用它们会创建循环依赖关系。然而,将它们放在trait上,使得所有扩展trait的类都可以覆盖它们,因此它们肯定不是应用程序范围的单例


Scala编译器是否“足够聪明”使trait中的final VAL变为“旧java公共静态final”

类似于
公共静态最终版
,您应该使用这样的伴生对象:

trait MyStuff
object MyStuff {
 val publicStaticFinal = ...
}
在本例中,
scalac
使用方法
public int publicStaticFinal()
创建一个单例对象(
publicStaticFinal MyStuff$MODULE$
)。如果愿意,可以将此方法设置为final

对于
public final
-使用
final val

trait MyStuff
 final val publicFinal = ...
}

在这种情况下,
scalac
创建了一个带有
public abstract int publicFinal()
的接口,并在
MyStuff
的每个祖先中实现它,因为
public final int publicFinal()

不,scala不会将trait中的
final val
转换为java
静态final
,,因为
final val
必须是继承类的实例成员(而不是静态成员)

scala> trait myStuff { final val Test="test" }
defined trait myStuff

scala> class t extends myStuff
defined class t

scala> t.Test
<console>:8: error: not found: value t
              t.Test
              ^

// we need an instance of t to access Test
scala> new t
res2: t = t@35612600

scala> res2.Test
res3: String = test

你关心的循环依赖性的一个例子是什么

通常,这可以通过在trait或lazy vals中适当使用def来解决

下面是由默认参数(在伴随对象中合成)诱导的

但如果你需要渴望,你可以提前定义:

但是,如果计算
w
使用
Foo
的成员,则您必须变得懒惰:

trait Foo {
  val v = 2 * Foo.w
  def x = 7
}
object Foo extends Foo {
  lazy val w = 3 * x
}
这是我今天第二次需要一个问题的常见问题,但我还没有找到它的新家


(编辑:为什么,)

访问
Test
而不使用
t
实例:
val-mine:myStuff=null;mine.Test
scala> :pa
// Entering paste mode (ctrl-D to finish)

trait Foo {
  val v = 2 * Foo.w
}
object Foo extends {
  private val w = 3
} with Foo

// Exiting paste mode, now interpreting.

defined trait Foo
defined object Foo

scala> Foo.v
res11: Int = 6
trait Foo {
  val v = 2 * Foo.w
  def x = 7
}
object Foo extends Foo {
  lazy val w = 3 * x
}