Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/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:为什么下划线(41;初始化只适用于字段而不适用于方法变量?_Scala - Fatal编程技术网

scala:为什么下划线(41;初始化只适用于字段而不适用于方法变量?

scala:为什么下划线(41;初始化只适用于字段而不适用于方法变量?,scala,Scala,这项工作: scala> class foo[T] { | var t: T = _ | } defined class foo 但这并不是: scala> def foo[T] = { | var t: T = _ | } <console>:5: error: local variables must be initialized var t: T = _ )这在(我的斜体)的4.2节中定义 变量定义v

这项工作:

scala> class foo[T] {
     | var t: T = _
     | }
defined class foo
但这并不是:

scala> def foo[T] = {
     |   var t: T = _
     | }
<console>:5: error: local variables must be initialized
         var t: T = _

)

这在(我的斜体)的4.2节中定义

变量定义
var x:T=.
只能作为模板的成员出现。信息技术 引入类型为
T
和默认初始值的可变字段


当然,这并不能回答为什么会这样

这里至少有一个我刚刚发现的用例。当超类通过反射初始化成员变量时,它实际上可以初始化子类成员变量。但是,如果子类也使用值初始化成员变量,那么这将具有覆盖超类给它的值的效果。这可以通过使用下划线初始化子类成员变量来避免。这就是为什么语言规范要给变量一个getter函数,该函数返回的当前值比oxbow_lake的句子中引用的句子稍微低一点。

Martin在这里回答:

它对应于JVM。可以省略字段初始化,但不能省略局部变量初始化。省略局部变量初始化意味着编译器必须能够为每种类型合成一个默认值。在类型参数、专门化等方面,这并不容易

当被问及在Scala合成默认值的问题上字段和局部变量之间有什么区别或应该有什么区别时,他接着说:

在字节码方面有明显的区别。默认情况下,JVM将初始化对象字段,并要求显式初始化局部变量。[…]我不确定我们是否应该打破Java的一个有用的原则(在使用局部变量之前必须初始化),或者我们是否应该像Java那样进行全文并引入基于流的初始化检查。这将是更好的解决方案,海事组织,但需要在规范和实施方面进行大量工作。面对这些选择,我的本能是现在什么都不做:-)

因此,如果我理解正确,Scala编译器实际上不会合成对象字段的默认值,它会生成字节码,让JVM来处理这个问题

根据Martin的协议,实际上认可了语言规范中的
null.asInstanceOf[T]
模式,似乎是因为无法在现有的约束条件下切实支持更好的替代方案

var t: T = null.asInstanceOf[T]