日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Scala中的延迟初始化(Lazy vals)

發(fā)布時(shí)間:2024/1/23 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Scala中的延迟初始化(Lazy vals) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

延遲初始化(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í)行順序:

  • 首先,創(chuàng)建了一個(gè)新的 LazyRationalTrait 的實(shí)例,執(zhí)行 LazyRationalTrait 的初始化代碼,這部分代碼為空,LazyRationalTrait 所有成員變量都沒有初始化。
  • 其次,該 Trait 的匿名子類的主構(gòu)造函數(shù)被執(zhí)行,這部分初始化 numberArg 和 denomArg 為2和4.
  • 接下來,命令行需要調(diào)用該實(shí)例的 toString 方法來顯示該實(shí)例的值。
  • 接下來,toString 需要訪問成員 number 這是第一次訪問該成員,因此 lazy val 初始化代碼被執(zhí)行。初始化代碼調(diào)用私有成員g,因此需要計(jì)算 g 的值,用到之前定義過的 numberArg 和 denomArg。
  • 接下來 toString 需要訪問成員 denom 這是第一次訪問該成員,因此 lazy val 初始化代碼被執(zhí)行。初始化代碼調(diào)用私有成員 g ,因此需要計(jì)算 g 的值,因?yàn)?g 已經(jīng)計(jì)算過,無需再計(jì)算。
  • 最后,toString 的結(jié)果1/2構(gòu)造出來并顯示。
  • 在這個(gè)例子中,我們?cè)趯懘a時(shí),g 定義在 number 和 denom 的后面,然而,由于這三個(gè)變量都是使用 lazy 來定義的,因此它們?cè)诖a中出現(xiàn)的順序并不重要。

    總結(jié)

    以上是生活随笔為你收集整理的Scala中的延迟初始化(Lazy vals)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。