Updating immutable objects

守給你的承諾、 提交于 2019-12-11 02:45:21

问题


I have the following class built:

class Player(val name: String, val onField: Boolean, val draft: Int, val perc: Int, val height: Int, val timePlayed: Int) {
override def toString: String = name

}

I'm trying to do

def play(team: List[Player]): List[Player] =
team map (p => new Player(p.name, p.onField, p.draft, p.perc, p.height, p.timePlayed + 1))

which is actually incrementing the field "timePlayed" by one, and return the new "List" of players.

Is there a more convenient way to do this? Perhaps:

def play(team: List[Player]): List[Player] =
team map (p => p.timeIncremented())

My question is how to implement timeIncremented() in a more convenient way? so that I don't have to do:

new Player(p.name, p.onField, p.draft, p.perc, p.height, p.timePlayed + 1)

Thanks!


回答1:


You can use define Player as case class and use compiler generated method copy:

case class Player(name: String, onField: Boolean, draft: Int, perc: Int, height: Int, timePlayed: Int) {
    override def toString: String = name
}

def play(team: List[Player]): List[Player] =
    team map (p => p.copy(timePlayed = p.timePlayed + 1))

Also, as you see, constructor parameters are val by default.

And you can define timeIncremented in Player and use it exactly as you want:

case class Player(name: String, onField: Boolean, draft: Int, perc: Int, height: Int, timePlayed: Int) {
    override def toString: String = name
    def timeIncremented: Player = copy(timePlayed = this.timePlayed + 1)
}

def play(team: List[Player]): List[Player] =
    team map (_.timeIncremented)

For more complex cases you can take a look at lenses:
http://akisaarinen.fi/blog/2012/12/07/boilerplate-free-functional-lenses-for-scala/
Cleaner way to update nested structures



来源:https://stackoverflow.com/questions/20211022/updating-immutable-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!