我正在使用Scala 2.11.1和akka 2.3.8
假设我有一个班级
case class Person(firstName : String, var lastName : String,var age : Int, doB : DateTime)
我很困惑,我应该将val
用于所有属性,还是应该为var
寻找可以在将来变异的属性
请指导我做什么更好的方法,记住我在演员消息传递中使用此类的对象
编辑:
另外请告诉我一个线程是否来了并更改了该类的属性,这是一个到位突变还是一个新的对象将与更改的属性一起形成?
答案 0 :(得分:2)
首先,我认为在这种情况下你不应该同时拥有age
和doB
。你在寻找麻烦。仅使用doB
并在需要时计算年龄,价格便宜。对于初学者来说,doB
是不变的,年龄会发生变化。这是域名,与Scala或Akka无关。此外,由于这是一个消息,Data Transfer Object,它不应该有变异的需要,它没有很长的生命周期,恕我直言。
这可能解决了你的具体问题,但一般情况下,如果你真的需要变异,那么请将其设为var
。但又一次,考虑一下你是否需要它。如果您需要更改它,那么创建一个setter,它创建一个新的,也是不可变的对象,具有与前一个相同的属性,但更改了一个属性。
编辑:
由于您向问题添加了详细信息,可能需要一些其他说明。
如果您正确使用Akka,则不必担心线程会更改对象。每个actor都是一个独立的线程,它拥有自己独立的范围。这意味着从ActorA
发送到ActorB
的邮件是副本。在ActorB
中更改邮件不会更改ActorA
范围内的任何数据。请记住,演员应该只根据他们收到的消息做出反应。一个活动,不应该干扰另一个,考虑到他们不共享资源,如数据库,这是另一个故事。
@ccheneson通过编辑一些属性来解释如何从现有对象创建新的不可变对象。使用copy
方法时,您会获得两个对象,您复制的原始对象(未更改)和新修改的对象。如果你这样做,例如:
val p1 = Person("Aleksandar","Stojadinovic",25,"1970-01-01") //mocking the date, ignoring I advised you not to use age, and look what I was allowed to do ^.^
p1.age=28
println(p1.age) //outputs 28
您的p1
现已更改。如果您使用常规线程而不是Akka,则可能会遇到线程同步和Reader-Writer problem
如果你正在尝试,那么你不应该在一个actor中运行线程。
答案 1 :(得分:1)
Aleksandar Stojadinovic对age
和doB
有一个很好的观点。
我只想补充一点,您可以将所有属性保留为val
,如果需要更改属性值,请使用copy
方法(随case class
免费提供)并更改所需的属性。 copy
将返回一个新的Person
对象,其中您的属性已更新
scala> case class Person(firstname: String, lastname:String)
defined class Person
scala> val p1 = Person("John", "Doe")
p1: Person = Person(John,Doe)
scala> val p2 = p1.copy(lastname = "Wayne")
p2: Person = Person(John,Wayne)