2012-10-22 7 views
5

Ho riscontrato un comportamento un po 'bizzar negli oggetti che si estende App. dare un'occhiata al seguente REPL comandi:cosa succede in scala quando si caricano oggetti che estendono l'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 

bene, questo è un po 'strano ... ma diventa più strano. Allora ho pensato che le vals in un object vanno in qualche valutazione pigra ... così ho provato un vero e proprio 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? 

così che cosa sta succedendo qui? perché una val regolare ottiene un valore nullo?
perché questo comportamento cambia quando utilizzo lazy val?
e cosa c'è di così speciale con il tratto App, che rende i valori normali non valutati?

risposta

9

L'app estende DelayedInit tratto. Quindi tutte le istruzioni e tutte le definizioni di valore vengono spostate nel metodo delayedInit. Lazy val funziona perché compila il metodo.

Per esempio se si decompilare questa classe:

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

Otterrete classe con 'metodo pigro':

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; 
} 

e il metodo delayedInit in classe interna 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; 
.... 

Il valore "I am null" sarà assegnato al campo test solo quando d viene chiamato elayedInit.

Problemi correlati