回答
如果對象的用戶沒有辦法讓它變異,則對象是不可變的。這意味着它不必重新分配其任何成員變量或改變這些變量引用的任何對象。如果所有對象的成員都是val
,這確保前者(即它們不能被重新分配),而不是後者(即,如果由這些變量引用的對象本身是可變的,則它們仍然可以通過調用變異方法即使他們僅被val
s引用)。
還要注意的是,即使成員被聲明爲var
S,對象仍然是不可變的,如果沒有一個對象的方法實際上是重新分配變量(或叫突變它們的方法) - 假設的過程中,它們是私有的。
因此只有val
成員對於一個對象是不可變的既不必要也不足夠。無論對象是由val
還是var
(或兩者)引用都沒有什麼區別。
@ sepp2k很好地正確地解釋了一個對象的標準是在技術上不可變。他的答案中遺漏的一個微妙之處是並非所有成員變量都對應於外部可見的狀態。成員也可以是例如一個緩存的內部值,用於存儲一些本地難以計算的數據,這些數據不能從外部直接看到(因此在Scala中被限定爲private[this]
)。一個對象可以有這樣的一個成員,例如存儲計算出的散列值。它甚至可以通過公共getter訪問 - 只要訪問器的行爲是純粹的功能,即它總是爲同一對象上的每次調用產生相同的值(除了在重用內部緩存值時它的返回速度更快)。
Scala編譯器知道這個區別,所以它可以幫助你正確地實現一個不可變類,即使在內部使用可變狀態。當泛型類型變化發揮作用時,這很重要。也就是說,即使類包含這種類型的可重新分配字段,編譯器也允許泛型類型參數協變 - 只要這些字段是private[this]
,確保不能引用包含比靜態類型更弱的類型的對象類型的對象被定義爲(這將是導致類型錯誤的方差的前提條件)。
這將在Programming in Scala的第19.7節中詳細說明,代碼示例如下。
- 1. 在scala對象中,是不可變的val線程安全嗎?
- 2. 爲什麼我的不可變對象突變Scala
- 3. scala中的對象
- 4. Scala對象:作爲DAO的Scala對象
- 5. javascript:File對象是不可變的嗎?
- 6. jQuery對象是不可變的?
- 7. ReadonlyCollection,對象是不可變的嗎?
- 8. 是System.Security.SecureString對象是不可變還是可變的?
- 9. 轉化Scala的可變參數爲Java對象...可變參數
- 10. Scala - fromPublisher不是對象的成員akka.stream.scaladsl.Source
- 11. 不可變對象內的可變對象
- 12. 可變對象和不可變對象之間的區別
- 13. 如何使Scala的不可變集合保存不可變對象
- 14. 對於不可變的最終單件對象的值或對象
- 15. 將終結器中的底層對象置於不可變對象中
- 16. 對於Range對象(不是選擇對象),Word中的InsertStyleSeparator
- 17. 可變的Scala集合中的無對象
- 18. 與對象initialisers不可變對象
- 19. 爲什麼不可變的對象拋出UnboundLocalError但可變的對象不?
- 20. 不可變的對象是否可以免於不適當的發佈?
- 21. 克隆Java中的不可變對象
- 22. PHP中的不可變對象?
- 23. 對象不可變與對象的引用是不可變的是什麼區別?
- 24. 對於OOP,是不可變的和不變的同義詞?
- 25. Scala中的對象Mockito
- 26. scala中的伴隨對象
- 27. Scala中的所有對象
- 28. Scala中函數的平等是Scala中的函數對象嗎?
- 29. 任何方式來從C#中的不可變對象派生可變對象?
- 30. 包裝對象中的不可變對象引用
維基百科[似乎同意你](http://en.wikipedia.org/wiki/Immutable_object#Scala)。 –
@RobertHarvey然後維基百科是錯誤的。如果一個對象被一個'val'引用,並且它的所有成員都是'val's,如果它的成員是可變的,它仍然可以是可變的。即使被「var」引用,一個不可變對象也是不可變的。 – sepp2k
@ sepp2k:在你回答這個問題之後,你是否會修好維基百科條目以及如此好? :) –