Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala:使用硬编码值的特征初始化代码_Scala_Oop_Inheritance_Overriding_Traits - Fatal编程技术网

Scala:使用硬编码值的特征初始化代码

Scala:使用硬编码值的特征初始化代码,scala,oop,inheritance,overriding,traits,Scala,Oop,Inheritance,Overriding,Traits,以下代码: trait A{ val s: String = "A" println(s"A's initialiser run, s= $s") } object O1 extends A { override val s = "O1" println(s"Object's initialiser run, s= $s") def foo: Unit = println("I am just being called to instantiate the object!

以下代码:

trait A{
  val s: String = "A"
  println(s"A's initialiser run, s= $s")
}

object O1 extends A {
  override val s = "O1"
  println(s"Object's initialiser run, s= $s")

  def foo: Unit = println("I am just being called to instantiate the object! :| ")
}

object O2 extends AnyRef with A {
  override val s = "O2"
  println(s"Object's initialiser run, s= $s")

  def foo: Unit = println("I am just being called to instantiate the object! :| ")
}

println("////with inheritance:")
O1.foo
println("////with mix-in:")
O2.foo
印刷品:

////with inheritance:
A's initialiser run, s= null
Object's initialiser run, s= O1
I am just being called to instantiate the object! :| 
////with mix-in:
A's initialiser run, s= null
Object's initialiser run, s= O2
I am just being called to instantiate the object! :| 
我觉得这种行为很奇怪。我预计会出现以下行为之一:

  • “…s=O1”
    “…s=O1”
  • “…s=A”
    “…s=O1”
但两者都没有发生

s
被保留为抽象
val
,而不是
def
,我可以理解类似的行为,但我发现忽略该值很奇怪。我的问题是:

  • 表面下发生了什么导致了这种行为
  • 编译器对在带有硬编码值的trait与带有抽象值的trait中运行初始化块的情况有多相似/不同
  • 为什么Scala决定这样做,而不是上面详述的两个预期场景
  • 编译器不应该警告我们在traits的主体中除了值设置之外还有什么吗

    • 这是由
      s
      is重写子类引起的,Scala编译器将其转换为抽象val,如:

      public abstract java.lang.String s();
      
      s
      将在所有
      superclass
      完成初始化(
      A
      )后初始化,
      superclass
      完成初始化后,它只会初始化一次(在
      O1
      O2
      ),因此,当
      A
      的初始化块尝试打印
      s
      时,将得到
      null

      还有一个参考资料很有帮助: