开发者

scala: why does underscore (_) initialization work for fields but not method variables?

this works:

scala> class foo[T] {
     | var t: T = _
     | }
defined class foo

but this doesn't:

scala> def foo[T] = {
     |   var t: T = _
     | }
<console>:5: error: local variables must 开发者_运维问答be initialized
         var t: T = _

why?

(one can use:

var t: T = null.asInstanceOf[T]

)


There is a mailing list thread where Martin answered:

It corresponds to the JVM. You can omit a field initialization but not a local variable initialization. Omitting local variable initializations means that the compiler has to be able to synthesize a default value for every type. That's not so easy in the face of type parameters, specialization, and so on.

When pressed about how there is or should be any distinction between fields and locals in the matter of Scala synthesizing default values, he went on to say:

In terms of bytecodes there IS a clear difference. The JVM will initialize object fields by default and require that local variables are initialized explicitly. […] I am not sure whether we should break a useful principle of Java (locals have to be initialized before being used), or whether we should rather go the full length and introduce flow-based initialization checking as in Java. That would be the better solution, IMO, but would require significant work in terms of spec and implementation. Faced with these choices my natural instinct is to do nothing for now :-)

So if I understand correctly, the Scala compiler does not actually synthesize default values for object fields, it produces bytecode that leaves the JVM to handle this.

According to SI-4437 there was agreement from Martin on actually endorsing the null.asInstanceOf[T] pattern in the language spec, seemingly for lack of being able to feasibly support a better alternative within existing constraints.


This is defined in section 4.2 of the Scala Language Specification (my italics)

A variable definition var x: T = _ can appear only as a member of a template. It introduces a mutable field with type T and a default initial value

This, of course, does not answer the why this should be so!


Here is at least one use case that I just uncovered. When then superclass initializes member variables via reflection it can actually initialize a subclasses member variables. However, if a subclass also initializes the member variable with a value, then this will have the effect of overwriting the value that the superclass gave it. This can be avoided by initializing the subclasses member variable with the underscore. This is why the language spec talks about giving the variable a getter function that returns the current value a little further down from the quoted sentence in oxbow_lake's sentence.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜