Well... all the parameter attributes
in the case classes
are immutable
by default.
This is done with the purpose of promoting thread-safe
programming. Also, one major thing that should be noticed is that this in a way also promotes the original idea of OOP ( the one similar to Smalltalk, before being transformed by Java OOP ).
Well... Separation of state and behaviour. So... basically kind of the ideal situation where Separation of state and behaviour
meets thread-safety
.
My personal taste for doing this would be - Have state
in the case class
, and move all behaviour
to companion object
.
case class User( userId: Int, userName: String, email: String, password: String )
object User {
def apply(): User = User( 0, "", "", "" )
}
case class Team( teamId: Int, teamName: String, teamOwner: Int, teamMembers: Seq[ User ] )
object Team {
def apply(): Team = Team( 0, "", 0, Nil )
// since addMember is a behavior, it belongs here.
// Also... since we are immutable... addMember name does not make much sense...
// Let's call it withMember
def withMember( team: Team, user: User ): Team = {
team.copy( teamMembers = team.teamMembers :+ user )
}
}
Now, you will have to use it like this,
val user = User()
val team = Team()
val teamWithMember = Team.withMember( team, user )
But... In case... ( like in a really rare case ), if you "really" want ( control your desires man... control ) to have it mutable then
case class Team( teamId: Int, teamName: String, teamOwner: Int, var teamMembers: Seq[ User ] )
object Team {
def apply(): Team = Team( 0, "", 0, Nil )
// since addMember is a behavior, it belongs here.
// Now we can keep name addMember
def addMember( team: Team, user: User ): Unit = {
team.teamMembers = team.teamMembers :+ user
}
}
And use it like this,
val user = User()
val team = Team()
team.addMember( user )