2012-10-22 10 views
5

मुझे App तक फैली वस्तुओं में कुछ हद तक विचित्र व्यवहार का सामना करना पड़ा है। ले निम्नलिखित आरईपीएल पर एक नज़र आदेश:ऐप को विस्तारित करने वाली वस्तुओं को लोड करते समय स्कैला में क्या होता है?

scala> object A extends App {val x = "I am null"} 
defined module A 

scala> object B {val x = "I am a string"} 
defined module B 

scala> A.x 
res0: java.lang.String = null 

scala> B.x 
res1: java.lang.String = I am a string 

अच्छी तरह से, यह थोड़ा अजीब है ... लेकिन यह weirder हो जाता है। मैं तो सोचा था कि एक object में Vals कुछ आलसी मूल्यांकन में जाने ... तो मैं एक असली lazy val की कोशिश की:

scala> object C extends App {lazy val x = "What am I?"} 
defined module C 

scala> C.x 
res2: java.lang.String = What am I? 

तो यहाँ क्या हो रहा है? एक नियमित वैल क्यों एक शून्य मूल्य मिलता है?
जब मैं lazy val का उपयोग करता हूं तो यह व्यवहार क्यों बदलता है?
और App विशेषता के साथ इतना खास क्या है, जो नियमित vals को अवमूल्यन बनाता है?

उत्तर

9

ऐप DelayedInit विशेषता बढ़ाता है। तो सभी कथन और सभी मूल्य परिभाषाएंdelayedInit विधि पर ले जाया गया है। आलसी वैल काम करता है क्योंकि यह विधि के लिए संकलित करता है।

उदाहरण के लिए यदि आप इस वर्ग डिकंपाइल:

class TestApp extends App{ 
    val test = "I am null" 
    lazy val testLazy ="I am a string" 
} 

आप आलसी विधि 'के साथ वर्ग मिल जाएगा:

public String testLazy() 
{ 
    if((bitmap$0 & 1) == 0) 
     synchronized(this) 
     { 
      if((bitmap$0 & 1) == 0) 
      { 
       testLazy = "I am a string"; 
       bitmap$0 = bitmap$0 | 1; 
      } 
      BoxedUnit _tmp = BoxedUnit.UNIT; 
     } 
    return testLazy; 
} 

और delayedInit विधि में भीतरी वर्ग delayedInit.body:

public final class delayedInit.body extends AbstractFunction0 
     implements ScalaObject 
    { 

     public final Object apply() 
     { 
      $outer.test_$eq("I am null"); 
      return BoxedUnit.UNIT; 
     } 

     private final TestApp $outer; 
.... 

तो मूल्य "मैं शून्य हूं" को केवल test फ़ील्ड को असाइन किया जाएगा जब डी elayedInit कहा जाता है।

संबंधित मुद्दे