2011-07-12 41 views
15

在水星我可以使用:斯卡拉是否有記錄更新語法,用於製作不可變數據結構的修改克隆?

A = B^some_field := SomeValue 

至A與B結合的副本,除了some_fieldSomeValue,而不是不管它是B.我相信哈斯克爾相當於是一樣的東西:

a = b { some_field = some_value } 

斯卡拉是否有這樣的「修改」不可變的值。替代似乎是有一個構造函數直接設置實例中的每個字段,這並不總是理想的(如果有構造函數應該維護的不變量)。另外,如果我必須明確地傳遞我想要修改副本的實例中的所有其他值,它將非常笨重並且更加脆弱。

我找不到任何關於這個的搜索結果,或者通過對語言參考手冊或「Scala示例」的簡短調查(我已經閱讀開始到結束,但尚未吸收所有內容,所以它可能在那裏)。

我可以看到,這個功能可以與Java風格訪問保護和子類,雖然一些奇怪的相互作用...

+1

是不是你要找的案例類? http://daily-scala.blogspot.com/2010/01/case-classes-in-28.html –

+0

另請參閱http://stackoverflow.com/questions/3900307/cleaner-way-to-update-nested-結構 –

回答

11

您可以爲此使用大小寫類,但您不必。案例類沒有什麼神奇的 - 修飾符case只是爲您節省了大量的輸入。 複製方法通過使用命名參數和默認參數來實現。名稱與字段相同,默認值是字段的當前值。下面是一個例子:

class ClassWithCopy(val field1:String, val field2:Int) { 
    def copy(field1:String = this.field1, field2:Int = this.field2) = { 
     new ClassWithCopy(field1,field2); 
    } 
} 

您可以像使用案例類的複製方法一樣使用它。命名參數和默認參數是非常有用的功能,不僅適用於複製方法。

+2

哇,我怎麼會錯過Scala已經命名參數傳遞?這將非常有用。我接受了這個答案,因爲它解釋了案例類的複製方法是如何工作的,以及即使案例類不合適也能如何應用這些想法。 – Ben

4

如果你在修改計劃的對象是一個案例類,那麼你可以使用自動生成的複製方法:

scala> val user = User(2, "Sen") 
user: User = User(2,Sen) 

scala> val corrected = user.copy(name = "Sean") 
corrected: User = User(2,Sean) 
26

如果你定義類作爲case class,產生一種方便的方法copy,並調用它,您可以對某些字段命名參數的新值指定。

scala> case class Sample(str: String, int: Int) 
defined class Sample 

scala> val s = Sample("text", 42) 
s: Sample = Sample(text,42) 

scala> val s2 = s.copy(str = "newText") 
s2: Sample = Sample(newText,42) 

它甚至多態case類作品:

scala> case class Sample[T](t: T, int: Int) 
defined class Sample 

scala> val s = Sample("text", 42) 
s: Sample[java.lang.String] = Sample(text,42) 

scala> val s2 = s.copy(t = List(1,2,3), 42) 
s2: Sample[List[Int]] = Sample(List(1, 2, 3),42) 

注意s2有不同的類型s

+0

非常感謝編輯,盧卡斯,我剛剛學到了一些新的東西! –

+0

感謝您的出色例子!多態拷貝非常漂亮。 – Ben