來自java背景我總是將實例變量標記爲私有。我正在學習scala,並且幾乎所有我查看過的代碼中的val/var實例都具有默認(公共)訪問權限。爲什麼這是訪問?它不會破壞信息隱藏/封裝原則嗎?爲什麼不將val或var變量標記爲私有?
回答
這將幫助您指定其中代碼,但請記住,某些示例代碼是以簡化形式突出顯示示例應該顯示給您的內容。由於默認訪問是公開的,這意味着爲了簡單起見,您經常會忽略修飾符。
這就是說,由於val
是不可改變的,有沒有在留公衆多大的危害只要你認識到這是現在你類的API的一部分。這可以是完全沒問題:
class DataThingy(data: Array[Double) {
val sum = data.sum
}
或者,它可以是一個實現細節,你不應該暴露:
class Statistics(data: Array[Double]) {
val sum = data.sum
val sumOfSquares = data.map(x => x*x).sum
val expectationSquared = (sum * sum)/(data.length*data.length)
val expectationOfSquare = sumOfSquares/data.length
val varianceOfSample = expectationOfSquare - expectationSquared
val standardDeviation = math.sqrt(data.length*varianceOfSample/(data.length-1))
}
在這裏,我們已經充斥我們班所有的中間步驟計算標準偏差。這是非常愚蠢的,因爲這不是用數字計算標準偏差最具數字穩定性的方法。
而不是僅讓這些私人的,它是更好的風格,如果可能的話,使用本地塊或private[this]
DEFS執行中間計算:
val sum = data.sum
val standardDeviation = {
val sumOfSquares = ...
...
math.sqrt(...)
}
或
val sum = data.sum
private[this] def findSdFromSquares(s: Double, ssq: Double) = { ... }
val standardDeviation = findMySD(sum, data.map(x => x*x).sum)
如果你需要存儲一個計算以供以後使用,那麼private val
或private[this] val
是要走的路,但如果它只是計算的中間步驟,則上述選項更好。
同樣,如果它是接口的一部分(如可變向量上的向量座標),則公開var
並沒有什麼壞處。但是,當它是一個實現細節時,你應該使它們成爲private
(更好的是:private[this]
,如果可以的話!)。
實際上,一些Scala開發者傾向於使用默認訪問。但是你可以在着名的Scala項目中找到合適的例子(例如Twitter的Finagle)。
另一方面,將對象創建爲不可變值是Scala中的標準方法。如果完全不可變,我們不需要隱藏所有的屬性。
[*只是一個音符*]事實上,'val'不保證完整的不變性。對於它只是確保對該對象的引用是不可變的。 –
Java和Scala之間的一個重要區別是,在Java中,您不能用getter和setter方法(反之亦然)替換公共變量而不破壞源和二進制兼容性。在斯卡拉你可以。
所以在Java中,如果你有一個公共變量,它是一個變量的事實將暴露給用戶,如果你改變它,用戶必須改變他的代碼。在Scala中,您可以使用getter和setter方法(或僅使用getter方法的公共val
)替換公開的var
,而用戶不知道其差異。所以從這個意義上說,沒有實現細節暴露。
舉個例子,讓我們考慮一個矩形類:
class Rectangle(val width: Int, val height:Int) {
val area = width * height
}
如果我們稍後決定,我們不希望區域存儲爲一個變量現在發生了什麼,而是應該每次被調用時計算一次?
在Java中的情況會是這樣的:如果我們使用一個getter方法和一個私有變量,我們可以只取出變量和更改getter方法來計算面積,而不是使用的變量。不需要更改用戶代碼。但由於我們使用的公共變量,我們現在不得不打破用戶代碼:-(
在Scala中是不同的:。我們只能改變val
到def
,這就是它沒有更改需要用戶代碼
我想回答有一點更通用的方法的問題。我認爲你正在尋找的答案與上Scala是建立在設計範例做,而是經典的prodecural /面向對象的方法,如你看在Java中,函數式編程用於高得多的延伸。我不能涵蓋所有你提到課程的代碼,但一般(寫得很好)Scala代碼並不需要很多的可變性。
正如雷克斯指出的那樣,val
是不可改變的,所以他們不公開的原因很少。但正如我所看到的那樣,不變性本身不是一個目標,而是函數式編程的結果。所以如果我們認爲功能像x -> function -> y
那樣function
部分變得有點黑盒子;我們並不在意它的作用,只要它能正確地做。由於Haskell Wiki寫道:
純功能程序通常對不可變數據進行操作。與其更改現有值,不創建更改的副本並保留原始文件。
這也解釋了缺失的閉合,因爲我們傳統上想要隱藏的部分在函數中執行,因此無論如何都隱藏了。
所以,切東西短,我認爲可變性和封閉Scala中變得更加多餘。爲什麼在可以避免的情況下與吸氣劑和二次吸盤混淆?
- 1. 爲什麼我不能將普通變量設置爲私有或公共?
- 2. 爲什麼PHP私有類var不是私有的?
- 3. 爲什麼建議將實例變量聲明爲私有?
- 4. 爲什麼resharper認爲私有隻讀變量可以爲null?
- 5. 的JavaScript - 通過URL傳遞變量:#VAR = VAL VS VAR = VAL
- 6. 爲什麼$()。val()有時不起作用?
- 7. JS模塊模式 - 爲什麼不刪除私有變量
- 8. 爲什麼這個朋友不能訪問私有變量?
- 9. 爲什麼你不能在Kotlin中指定var/val循環?
- 10. 爲什麼我的私有變量設置爲空?
- 11. 爲什麼我需要將`var value = val;`更改爲`this.value = val;`所以我沒有收到「未定義」的錯誤?
- 12. 爲什麼變量不變?
- 13. 爲什麼Count()不適用於「Var」或「iQueryable」類的空記錄?
- 14. 爲什麼要將一個值提取到'var'變量的變化行爲?
- 15. 抽象類,爲什麼我們不能聲明私有的val和var類成員?
- 16. 爲什麼我需要在有私有變量時使引用保持不變?
- 17. 爲什麼沒有var?
- 18. 將變量連接爲jQuery val()參數?
- 19. 爲什麼將ImageView標記爲錯誤?
- 20. PhpStorm將現有變量標記爲「未解決變量」
- 21. OO PHP將所有私有變量作爲變量返回
- 22. 爲什麼VAR不能被應用到成員變量
- 23. 爲什麼要使用VAR爲變量類型
- 24. 爲什麼REPL將clojure.core/doc視爲var?
- 25. 爲什麼java允許私有字符串[] [] var []
- 26. 爲什麼變量有時不分配?
- 27. 爲什麼PHP $ _SESSION改變標記變量?
- 28. 爲什麼HttpUtility.UrlPathEncode標記爲「不使用」?
- 29. 爲什麼在讀回私有類變量時會得到EXC_BAD_ACCESS?
- 30. 爲什麼鼓勵使用處理程序的私有變量?
您對隱藏區塊中的中間步驟有何看法?這將很難在評論系統中格式化,但基本上val standardDeviation = {val sumOfSquares = ...; val expectationSquared = ...; var varianceOfSample = ...; math.sqrt(data.length * varianceOfSample /(data.length -1))} – joev
@joev - 這就是做事的好方法 - 往往更好,其實比離開私有變量。沒有辦法在他們完成之後讓他們坐在一起佔用空間。 –
@Rex Kerr'如果它是接口的一部分,暴露var就沒有什麼壞處 - 當我們使用接口的一部分時,我們不應該讓'var'-s是volatile嗎? – idonnie