2015-02-23 19 views
4

我定義一個類:斯威夫特:覆蓋對象的方法

class Person { 
    func speak(phrase: String) { 
     NSLog("\(phrase)") 
    } 
} 

假設我想改變speak方法的行爲。在java中,我會覆蓋此方法:

Person p = new Person() { 
    @Override 
    public void speak(String phrase) { 
     // Do something different 
    } 
}; 

如何重寫Swift中的方法?我嘗試了以下無濟於事:

let person = Person() 
person.speak = { (String) ->() in 
    // Do something different 
} 

錯誤:Cannot assign to 'speak' in 'person'

我知道我可以設置一個變量來改變行爲或子類的人,但我想不同的使用情況,其中像這是必要的。使用這個例子更容易解釋。

回答

4

以這種方式在斯威夫特不能創建匿名類,而必須派生新類:

class AnotherPerson: Person { 
    override func speak(phrase: String) { 
     NSLog("\(phrase) overidden!") 
    } 
} 

最接近的匿名實例重寫特定的方法是讓speak功能特性:

class Person { 
    var speak: (String)->() = { (phrase: String) in 
     println(phrase) 
    } 
} 

let person = Person() 
person.speak("Frank") // => Frank 
person.speak = { (phrase: String) in println("Hi, \(phrase)") } 
person.speak("Frank") // => Hi, Frank 

如果你不想隨機消費者能夠修改speak,你可以把它let屬性通過初始化設置:

class Person { 
    let speak: (String)->() 

    init(speaker: (String)->() = println) { 
     speak = speaker 
    } 
} 

Person().speak("Frank") // => Frank 
Person({ println("Hi, \($0)") }).speak("Frank") // => Hi, Frank 

let person = Person() 
person.speak = { println($0) } // error: cannot assign to speak 

這裏我們將默認設置爲println,因此保留了原始的默認行爲。

+0

編輯:包括使用函數屬性來模擬想要的內容。 – mxcl 2015-02-23 17:16:39