[英]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
+=
具有相應的簽名。 另一方面,對於大多數合同而言,沒有辦法強制執行以遵守合同。 例如,總是返回0
的size
的實現在技術上匹配所有類型,但顯然違反了合同。
同樣, Immutable
doc說:
所有不可變數據結構(如不可變集合)的標記特征。
因此,它只是一種標記trait
,它是解決無法真正表示為類型的合同的方法之一。 它說任何實現這種特性的人都聲稱自己是一個不可改變的對象。 您的代碼聲稱但明顯違反了合同。 所以從技術上講,不尊重合同是你的錯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.