Reputation: 4719
I have following classes
case class User(userId: Int, userName: String, email: String,
password:
String) {
def this() = this(0, "", "", "")
}
case class Team(teamId: Int, teamName: String, teamOwner: Int,
teamMembers: Seq[User]) {
def this() = this(0, "", 0, Nil)
}
I would like to add or User in teamMembers: Seq[User]. I tried couple of ways as:
Team.teamMembers :+ member
Team.teamMembers +: member
Nothing works :). Pleas advice me how can I add or remove item from teamMembers: Seq[User].
Thanks in advance!
Upvotes: 0
Views: 1534
Reputation: 7348
You didn't mention which Seq do you use.
If it's scala.collection.mutable.Seq
you can add to this Seq.
But, most changes that you use immutable.Seq which is Scala's default. This means you cannot add to a it, but you can create a new one with all items + new item.
With scala out of the box you can do it like this -
val team =Team(0,"", 0, Seq[User]())
val member = User(0, "","", "")
val teamWithNewMemebr = team.copy(teamMembers = team.teamMembers :+ member)
But this becomes pretty ugly if you have a lot of nesting or you have to do it a lot.
To overcome this complicated syntax you can use libraries like scalaz, monocle which provides you Lenses
Here's a good sample of how to use Lenses http://eed3si9n.com/learning-scalaz/Lens.html
Upvotes: 1
Reputation: 13985
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 )
Upvotes: 0
Reputation: 1609
Create an operation that returns a new Team with the member added, e.g.
The problem with your other code I think is you are trying to change an immutable variable. The teamMember field in the case class team is an immutable val and so changing it with an operation will not change what is contained in it - it will just return a new sequence with the value appended, but won't affect the one in the case class Team.
case class Team(teamId: Int, teamName: String, teamOwner: Int, teamMembers: Seq[User]) {
def this() = this(0, "", 0, Nil)
// Operation returns a new Team object which has all elements of the previous team plus an additional member appended to the team members.
def addMember(member: User) : Team = Team(teamId, teamName, teamOwner, teamMembers :+ member)
}
Upvotes: 1
Reputation: 272217
From the doc for the plus (+) operator:
[use case] A copy of the sequence with an element prepended
so +
will yield a new collection with your additional element prepended. Are you using this new collection.
Upvotes: 0