2013-11-26 207 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默認。

而且你可以定義PlayertimeIncremented,並用它完全按照你想要的:

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