簡體   English   中英

為什么我可以在scala中更新Object擴展不可變特征的狀態

[英]why I can update state of an Object extend immutable trait in scala

我創建了一個類擴展scala.Immutable

  class SomeThing(var string: String) extends Immutable {
      override def toString: String = string
  }

正如我所料,scala編譯器應該幫助我防止類SomeThing的更改狀態。 但是當我運行這個測試時

  "Test change state of immutable interface" should "not allow" in {
     val someThing = new SomeThing("hello")
     someThing.string = "hello 1"
     println(someThing)
  }

結果是hello 1 ,scala編譯器不會拋出任何警告或錯誤。

為什么他們必須添加不可變特性而不幫助我們防止對象變異?

這個問題有幾個方面。

1.一個簡單的問題是,Scala編譯器由於各種原因無法真正確保不可變性。 例如,主目標平台JVM允許使用反射修改final字段。 這是不可執行的另一個原因是像這樣的代碼

 /////////////////////////////////////////
 //// library v1
 package library

 class LibraryData(val value:Int)


 /////////////////////////////////////////
 //// code that uses the library
 package app

 class UserData(val data:LibraryData) extends Immutable



 /////////////////////////////////////////
 //// library v2
 package library

 class LibraryData(var value:Int) //now change it to var!

由於“庫”是獨立於“app”編譯的,甚至不知道“app”的存在,因此編譯器無法捕獲破碎的合同。

2.你似乎有更多根本性的誤解是什么trait呢。 在此上下文中, trait (或某些其他語言中的“ interface ”)表示實現與用戶代碼之間關於實現如何以及應該如何表現的契約 然而,並非所有類型的合約都可以表示為trait (至少不會使代碼超級復雜)。 例如,對於一個可變集合,有一個契約, size應該返回add (或+= )被調用的次數,但除了聲明有方法size+=之外,沒有辦法將這樣的契約表示為trait +=具有相應的簽名。 另一方面,對於大多數合同而言,沒有辦法強制執行以遵守合同。 例如,總是返回0size的實現在技術上匹配所有類型,但顯然違反了合同。

同樣, Immutable doc說:

所有不可變數據結構(如不可變集合)的標記特征。

因此,它只是一種標記trait ,它是解決無法真正表示為類型的合同的方法之一。 它說任何實現這種特性的人都聲稱自己是一個不可改變的對象。 您的代碼聲稱但明顯違反了合同。 所以從技術上講,不尊重合同是你的錯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM