Swift 結構體何時使用 mutating 函數
Swift 最棒的特點之一就是它內置了對整體結構的不可變性的支持,這使得我們的代碼更加整潔、安全(關于這個話題,如果還沒看過 這篇文章 ,那么強烈推薦給你)。
不過,真的需要用到可變性時,你應該怎么做呢?
函數式做法
舉個例子,我有一個井字棋棋盤,現在需要改變棋盤上某個位置的狀態:
struct Position {
let coordinate: Coordinate
let state: State
enum State: Int {
case X, O, Empty
}
}
struct Board {
let positions: [Position]
// 需要添加一個函數來更新這個位置的狀態
// 狀態從 Empty 改為 X 或者 0
}
如果完全采用 函數式編程的做法 ,你只需要簡單的返回一個新的棋盤即可:
struct Board {
let positionsMatrix: [[Position]]
init() {
// 初始化一個空棋盤的邏輯
}
// 函數式編程的做法
func boardWithNewPosition(position: Position) -> Board {
var positions = positionsMatrix
let row = position.coordinate.row.rawValue
let column = position.coordinate.column.rawValue
positions[row][column] = position
return Board(positionsMatrix: positions)
}
}
我更傾向于使用這種函數式的做法,因為它不會有任何副作用。變量可以繼續保持不可變狀態,當然,這樣也非常易于測試!
class BoardTests: XCTestCase {
func testBoardWithNewPosition() {
let board = Board()
let coordinate = Coordinate(row: .Middle, column: .Middle)
let initialPosition = board[coordinate]
XCTAssertEqual(initialPosition.state, Position.State.Empty)
let newPosition = Position(coordinate: coordinate, state: .X)
let newBoard = board.boardWithNewPosition(newPosition)
XCTAssertEqual(newBoard[coordinate], newPosition)
}
}
不過這種做法并非在所有場景下都是最佳選擇。
使用 Mutating 關鍵字
假設我需要統計每個用戶贏了多少局井字棋,那么我創建了一個 Counter:
struct Counter {
let count: Int
init(count: Int = 0) {
self.count = count
}
// 需要實現一個增加計數的方法
}
我依然可以選擇函數式的做法:
struct Counter {
let count: Int
init(count: Int = 0) {
self.count = count
}
// 函數式做法
func counterByIncrementing() -> Counter {
let newCount = count + 1
return Counter(count: newCount)
}
}
不過,如果你真的嘗試了使用這個函數來增加計數,代碼會是這樣:
var counter = Counter()
counter = counter.counterByIncrementing()
這種寫法不夠直觀,可讀性也不高。所以在這種場景下,我更傾向于使用 mutating 關鍵字:
struct Counter {
// 這個變量現在得聲明成 var
var count: Int
init(count: Int = 0) {
self.count = count
}
// 使用 mutating 關鍵字的做法
mutating func increment() {
count += 1
}
}
我不喜歡這個函數帶來的副作用,但是相對于可讀性的提升而言,這樣做是值得的:
var counter = Counter()
counter.increment()
更進一步來說,通過 使用私有 setter 方法 可以確保 count 變量不會被外部修改(因為它現在被聲明為變量了)。這樣,使用變異方法和變量所帶來的負面影響可以被降到最低。
總結
在選擇使用 mutating 關鍵字和函數式編程時,我傾向于后者,但前提是 不會以犧牲可讀性為代價 。
寫測試是一種很好的檢查接口的方法,它可以判斷你的函數式編程是否真的有意義。如果你覺得代碼比較奇怪而且不夠直觀,那么就換成 mutating 方法吧。只要記得使用變量的私有 setter 方法就行了。
來自: http://swift.gg/2016/06/17/when-to-use-mutating-functions-in-swift-structs/
本文由用戶 beckwith 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!