jlhonora
jlhonora

Reputation: 10699

Swift: Override object method

I'm defining a class:

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

Suppose that I want to change the behavior of the speak method. In java I would override this method:

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

How can I override the method in Swift? I tried the following to no avail:

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

Error: Cannot assign to 'speak' in 'person'

I know I could set a variable to change the behavior or subclass Person, but I'm thinking of a different use case where something like this is needed. Using this example was easier to explain.

Upvotes: 4

Views: 1636

Answers (1)

mxcl
mxcl

Reputation: 26883

You cannot create anonymous classes in this manner in Swift, instead you must derive a new class:

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

The closest to anonymous instantiations that override particular methods is to make speak a function property:

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

If you don’t want random consumers to be able to modify speak, you can make it a let property set via the initializer:

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

Here we set the default to println which thus preserves the original default behavior.

Upvotes: 4

Related Questions