Scala中的延迟初始化(Lazy vals)
延遲初始化(Lazy vals)
除了前面介紹的預(yù)先初始化成員值外,你還是讓系統(tǒng)自行決定何時(shí)初始化成員的初始值,這是通過在 val 定義前面添加 lazy(懶惰),也是說直到你第一次需要引用該成員是,系統(tǒng)才會(huì)去初始化,否則該成員就不初始化(這也是 lazy 的由來:-)).首先我們定義一個(gè)正常定義 val 的例子:
object Demo {val x = { println("initializing x"); "done"} }我們首先引用 Demo,然后 Demo.x
scala> Demo initializing x res0: Demo.type = Demo$@78178c35scala> Demo.x res1: String = done正如你所看到的,當(dāng)引用 Demo 對(duì)象時(shí),它的成員 x 也會(huì)初始化,初始化 x 伴隨著初始化 Demo 的過程。然后,如果我們?cè)?val x 前添加 lazy ,情況就有所不同了:
object Demo {lazy val x = { println("initializing x"); "done"} }defined object Demoscala> Demo res0: Demo.type = Demo$@7de1c412scala> Demo.x initializing x res1: String = done在使用 lazy 之后,初始化 Demo 時(shí),不會(huì)初始化 x,只有在引用到 Demo.x 該初始化代碼才會(huì)執(zhí)行。這有點(diǎn)類似定義了一個(gè)無參數(shù)的方法,但和 def 不同的是,lazy 變量初始化代碼只會(huì)執(zhí)行一次。通過這個(gè)例子,我們可以看到例如 Demo 的對(duì)象本身也像一個(gè) lazy 變量,也是在第一次引用時(shí)才會(huì)初始化,這是正確的,實(shí)際上一個(gè) object 定義可以看成是使用了lazy val定義一個(gè)匿名類實(shí)例的簡化方式。
使用l azy val,我們可以修改之前的 RationalTrait, 在這個(gè)新的 Trait 定義中,所有的類成員變量的實(shí)現(xiàn)(非抽象成員)都使用 lazy 來修飾。
trait LazyRationalTrait{val numerArg :Intval denomArg :Intlazy val numer = numerArg/glazy val denom = denomArg/gprivate lazy val g = {require(denomArg !=0)gcd(numerArg,denomArg)}private def gcd(a:Int,b:Int):Int =if(b==0) a else gcd(b, a % b)override def toString = numer + "/" + denom }同時(shí)我們把 require 移動(dòng)到 g 里面,這樣所有的 lazy val 初始化代碼都移動(dòng)到 val 定義的右邊。我們不再需要預(yù)先初始化成員變量。測(cè)試如下:
scala> val x = 2 x: Int = 2scala> new LazyRationalTrait{val numerArg = xval denomArg = 2 * x }res2: LazyRationalTrait = 1/2我們來分析一下這段代碼中命令行的執(zhí)行順序:
在這個(gè)例子中,我們?cè)趯懘a時(shí),g 定義在 number 和 denom 的后面,然而,由于這三個(gè)變量都是使用 lazy 來定義的,因此它們?cè)诖a中出現(xiàn)的順序并不重要。
總結(jié)
以上是生活随笔為你收集整理的Scala中的延迟初始化(Lazy vals)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: geometry-api-java 学习
- 下一篇: scala中使用Option、Some、