隨着盧卡斯和Venkat Sudheer雷迪Aedama在他們的評論中提到,在斯卡拉變異值的推薦的方法是使用不可變對象。
這意味着每次更改對象狀態時,您都將創建一個具有更新值的新對象。實現參照透明度是必要的,以允許程序免於副作用,這被認爲是令代碼更容易維護的理想屬性。
在Scala中有一個稱爲case類的簡便機制。讓我們來看看Door
是如何被定義爲一個案例類:
case class Door(name: String, open: Boolean) {
def opened(open: Boolean) = copy(open = open)
}
正如你可能已經注意到有是類參數之前沒有var
或val
。這是因爲如果每個參數都被假定爲val
,那麼默認情況下,case類是不可變的。
另一個區別是,它不使用new
運算符創建新實例,而是使用copy
方法,該方法允許更改指定字段的值。可能很難看出現在這樣做的好處,但當您處理更多字段的案例類時,它變得非常方便。現在
您可以實例Door
並以下列方式更新:
val door = Door("MyDoor", false)
door.name // "MyDoor"
door.open // false
val door2 = door.opened(true)
door2.name // "MyDoor"
door2.open // true
的情況下,類提供的另一個方便之處在於,你可以實例化它們不使用new
關鍵字,它是調用Door.apply("MyDoor", false)
一個語法糖。
到目前爲止,我們已經看到了如何爲不可變數據對象聲明和使用一個case類。但這是否意味着我們應該總是這樣宣佈我們的班級?
案例類的重要屬性是它們是透明的。這是由於他們的所有領域都暴露爲公衆val
s。當你想以與存儲對象相同的方式讀取對象的屬性時,這很有用。另一方面,如果你不想暴露你的對象的內部(所以你的類可以被稱爲不透明),例如爲了強制一些不變量,使用標準的Scala類可能是一個更好的主意。
對於與透明度和不透明度相關的一般規則和權衡,我推薦閱讀李浩一的文章Strategic Scala Style: Designing Datatypes。
在某些情況下,例如,如果你想提高性能或降低系統的內存佔用,你可能會決定使用代替可變類:
class Door(var name: String,
var open: Boolean) {
def openDoor(newDoorState: Boolean): Unit =
open = newDoorState
}
val door = new Door("MyDoor",true)
door.name // "MyDoor"
door.open // true
door.openDoor(false)
door.name // "MyDoor"
door.open // false
只需記住的是,不可變對象通常是傳遞數據的首選方式,您應該將程序設計爲在默認情況下是透明透明的,並且當它變得非常必要時,請考慮諸如將數據結構更改爲可變的微觀優化。
另外我會補充說,在斯卡拉有一個約定(源於Java)使用駱駝案例的類字段和方法,所以,而不是命名您的方法open_door
像原來的例子,你應該命名它openDoor
。
這將是值得一提的是OP應該使用'方法名稱camelCase',指出,通常最好使用第一種變種,如果他想創建一個新的對象,可能會創建一個'case class Door(name:String,open:Boolean)'而不是''copy''來實現'opened'方法。 –
如@盧卡斯如上所述: '情況下類門(名稱:字符串,ISOPEN:布爾值){ DEF執行Opendoor(newDoorState:布爾型):門= this.copy(ISOPEN = newDoorState) }' –
盧卡斯,Venkat Sudheer雷迪Aedama對於遲到的答覆我很抱歉,這確實是一個懶惰的答案。感謝您的建議,我現在更詳細地回答了我的答案。 – adamwy