Initializing a val lately

前端 未结 3 1358
旧时难觅i
旧时难觅i 2021-01-23 17:51

Is it possible to do that in Scala using only val:

class MyClass {
  private val myVal1: MyClass2 //.....????? what should be here?

  def myMethod1(param1: Int)         


        
3条回答
  •  有刺的猬
    2021-01-23 18:27

    To imitate a lazy "value" whose initial value might not be retrieved until after instance initialization completes (btw, there is nothing special about such objects, e.g. Swift have lazy properties that are even recommended to be declared as variables), you can introduce a wrapper to repeat the same logic that the Scala compiler generates internally for lazy values in Scala:

    class LazyVar[T] {
    
      private[this] var value$compute: () => T = () => null.asInstanceOf[T]
      @volatile private[this] var value$: T = null.asInstanceOf[T]
      @volatile private[this] var isInitialized$ = false
      @volatile private[this] var isComputed$ = false
    
      def value_=(value: T) = this.synchronized {
        if(!isInitialized$) {
          value$compute = () => value
          isInitialized$ = true
        }
        else throw new IllegalStateException("Already initialized")
      }
    
      def value: T = this.synchronized {
        if(!isInitialized$) throw new IllegalStateException("Not yet initialized")
        else if(isComputed$) value$
        else {
          value$ = value$compute()
          isComputed$ = true
          value$
        }
      }
    }
    

    Now you just have to change MyClass2 to LazyVar[MyClass2] keeping tha val keyword as you wanted:

    case class MyClass2(param: Int)
    
    class MyClass {
      private val myVal1: LazyVar[MyClass2] = new LazyVar[MyClass2]
    
      def this(param: Int) {
        this()
        println("Storing the result of an expensive function...")
        myVal1.value = new MyClass2(param)
      }
    
      def debug() = println(myVal1.value)
    }
    

    Now, if you write something like

    val myClass = new MyClass(42)
    myClass.debug
    myClass.debug
    

    you'll see the value is only computed once:

    Storing the result of an expensive function...
    MyClass2(42)
    MyClass2(42)
    

提交回复
热议问题