2015-07-28 19 views
1

我想了解如何在Swift中實現命令模式。到目前爲止,該代碼工作正常:在Swift中使用struct的變異方法的命令模式

class Subject 
{ 
    var value: Int = 0 

    func setValue(value: Int) { 
     self.value = value 
    } 
} 

class Command<T> 
{ 
    private var receiver: T 
    private var instructions: T -> Void 

    init(receiver: T, instructions: T -> Void) { 
     self.receiver = receiver 
     self.instructions = instructions 
    } 

    func execute() { 
     instructions(receiver) 
    } 
} 

var subject = Subject() 

println(subject.value) // "0" 

let instructions: Subject -> Void = { sub in Subject.setValue(sub)(2) } 
let command = Command<Subject>(receiver: subject, instructions: instructions) 
command.execute() 

println(subject.value) // "2" 

但是,如果我想接收器是一個struct而不是class,同樣的代碼無法正常工作。所以,如果我定義主題爲struct如下:

struct Subject 
{ 
    var value: Int = 0 

    mutating func setValue(value: Int) { 
     self.value = value 
    } 
} 

然後我得到的錯誤:「主題是無法轉換爲INOUT主題」上let instructions: Subject -> Void = { sub in Subject.setValue(sub)(2) }

我不知道如何解決這個問題。任何建議?

+1

這可能是困難的。請注意,Command init方法中的'self.receiver = receiver'已經創建了一個*獨立的結構體副本。 –

+0

如此真實......這讓我覺得如果由於糟糕的設計理念而導致出現此問題。通常,在struct(「value」)對象(?)上應用命令模式可能沒有什麼意義,謝謝! – George

回答

0

問題是,如果你想調用一個對象的類方法,你需要傳遞一個inout參數。這是通過在變量前面追加&完成:

Subject.setValue(&subject)(2) 

然而,你不能從一個匿名方法中做到這一點,你需要把它明確地類型作爲INOUT參數。

我認爲這個代碼應該工作,但是在我的情況下,它崩潰的Xcode遊樂場和Xcode的REPL:

struct Subject 
{ 
    var value: Int = 0 

    mutating func setValue(value: Int) { 
     self.value = value 
    } 
} 

class Command<T> 
{ 
    private var receiver: T 
    private var instructions: inout T -> Void 

    init(inout receiver: T, instructions: inout T -> Void) { 
     self.receiver = receiver 
     self.instructions = instructions 
    } 

    func execute() { 
     instructions(&receiver) 
    } 
} 

var subject = Subject() 

println(subject.value) // "0" 


var instructions: inout Subject -> Void = { sub in Subject.setValue(sub)(2) } 
let command = Command<Subject>(receiver: &subject, instructions: instructions) 
command.execute() 

println(subject.value) // "2"