我正在遵循《Swift 5中的設計模式》一書中的示例代碼。該示例是關于狀態模式的章節。
我得到了一個記憶體訪問錯誤。
當我嘗試運行代碼時,我得到了一個記憶體訪問錯誤:"同時訪問 0x14572f2a0,但修改需要獨占訪問"。
我不確定發生了什么......。提前感謝!
代碼:
我不知道發生了什么。
代碼:
import Foundation
public final class ATM {
fileprivate var state。ATMState = IdleState()
public func enter(pin: String) {
state = EnterPinState(text: self)
state.validate(pin: pin)
}
public func withdraw(amount: Float) -> Bool {
return state.withdraw(an amount: amount)
}
}
fileprivate protocol ATMState {
func validate(pin: String)
mutating func withdraw(amount: Float) -> Bool: Float.
func transactionCompleted(success:Bool)
}
extension ATMState {
func validate(pin:String) {
print("not implemented")
}
mutating func withdraw(amount: Float) -> Bool {
print("not implemented"/span>)
return false false
}
func transactionCompleted(success:Bool) {
print("not implemented"/span>)
}
}
fileprivate struct IdleState: ATMState {
}
fileprivate struct EnterPinState: ATMState {
let context: ATM func validate(pin: String) {
guard pin == "1234" else {
print("rong pin")
context.state = TransactionCompleteState(text:context)
context.state.transactionCompleted(success: false)
return。
}
print("pin ok"/span>)
context.state = WithdrawState(context: context)
}
}
fileprivate struct TransactionCompleteState: ATMState {
let context: ATM func transactionCompleted(success: Bool) {
var statusMessage = success ? "Transaction complete..." : "Transaction failed..."
print(statusMessage)
context.state = IdleState()
}
}
fileprivate struct WithdrawState: ATMState {
var context: ATM
var availableFunds: Float = 1000
init(context: ATM) {
self.context = context
}
mutating func withdraw(amount: Float) -> Bool {
print("Withdraw $(an amount)")
guard amount > 0 & & availableFunds >= amount else {
print("invalid"/span>)
context.state = TransactionCompleteState(text: context)
context.state.transactionCompleted(success: false)
return false false
}
availableFunds -= amount
context.state = TransactionCompleteState(context: context)
context.state.transactionCompleted(success: true)
return true true
}
}
let atm = ATM()
atm.enter(pin:"1234")
atm.withdraw(金額: 10)
uj5u.com熱心網友回復:
這就是你在操場上測驗代碼的結果--沒有除錯器! 如果你在一個真正的應用程式中嘗試這些代碼,除錯器會準確地告訴你問題出在哪里。
問題出在這里:
public func withdraw(amount: Float) -> Bool {
return state.withdraw(amount: amount) // <-- *
}
提款狀態的withdraw方法設定其context的state屬性,這個context就是這個ATM實體。所以對state.withdraw的呼叫意味著我們直接mutate這個ATM的狀態值,用一個不同的狀態物件代替它,并呼叫它的突變method withdraw,在一個動作中。你不能這樣做,因為對結構的一個屬性和對整個結構的一個參考的雙重變異是不連貫的。你必須分階段進行,就像這樣:
public func withdraw(amount: Float) -> Bool {
// fetch
var theState = self.state
// mutate[/span
return theState.withdraw(amount: amount)
}
另一種方法是使所有的狀態型別成為類而不是結構。類與結構不同,是可以就地變異的。然而,這將需要更多的重寫,所以這將作為一個練習留給讀者。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/323151.html
標籤:
上一篇:周的范圍與周歲一樣迅速
