2013-11-26 5 views
2

я следующий класс построен:Обновления неизменных объектов

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 

}

Я пытаюсь сделать

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)) 

который фактически увеличивающееся поле "timePlayed" один, и вернуть новый «Список» игроков.

Есть ли более удобный способ сделать это? Возможно:

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

Мой вопрос заключается в том, как реализовать timeIncremented() более удобным способом? так что мне не нужно:

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

Спасибо!

ответ

7

Вы можете использовать определить игрока, как case class и использовать компилятор сгенерированный метод 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)) 

Кроме того, как вы видите, параметры конструктора являются val по умолчанию.

И вы можете определить timeIncremented в Player и использовать его именно так, как вы хотите:

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) 

Для более сложных случаев вы посмотрите на линзах могут:
http://akisaarinen.fi/blog/2012/12/07/boilerplate-free-functional-lenses-for-scala/
Cleaner way to update nested structures

Смежные вопросы