Patrick Perini
Patrick Perini

Reputation: 22633

Overriding default value of instance var

Given class Obj,

class Obj: NSObject {
    var x = "x"
}

and its subclass, Obj1, how do you change the default value of var x?

Simply setting a new value would make the most sense, but it seems to error out...

class Obj1: Obj {
    var x = "y"
}

❗️ Cannot override with a stored property 'x'

Upvotes: 11

Views: 6332

Answers (4)

Felix Dumit
Felix Dumit

Reputation: 468

In swift 3 I've found that chrisco's solution doesn't work anymore, But it works if you declare the variable in the base class with private(set).

class Parent {
    private(set) var name = "Dad"
}

class Child: Parent {
    override var name: String { return "Son" }
}

Upvotes: 1

Chris Conover
Chris Conover

Reputation: 9039

This question has been marked answered, but there is also the safe-in-Swift template method pattern by way of delegation to a computed property:

class Foo {
    lazy var x : String = self.defaultX
    var defaultX:String { return "foo" }
}

class Bar : Foo {
    override var defaultX:String { return "bar" }
}


println(Foo().x) // foo
println(Bar().x) // bar

By safer, I am referring to Swift's enforcement of the initialization sequence that prevents problems with "virtual" calls into a not-yet constructed sub class (ie, having a base class call a virtual method that is implemented in a sub class, but before that subclass has finished initializing). This was a danger in C++, for example.

Upvotes: 6

Erik
Erik

Reputation: 12858

In most cases, injecting these values via init is the preferred way.

For example:

class Foo
{
    var x : String

    convenience init()
    {
        self.init(x: "x")  // 'x' by default
    }

    init(x: String)
    {
        self.x = x
    }
}

class Bar : Foo
{
    convenience init()
    {
        self.init(x: "y")   // now 'y' by default
    }

    init(x: String)
    {
        super.init(x: x)
    }
}

However, there are some cases where you want to override a computed property or perhaps something that is not exactly initialized.

In this case, you can use the override var syntax:

override var x : String
{
    get { return super.x }      // get super.x value
    set { super.x = newValue }  // set super.x value
}

The above code does not change the behavior, but illustrates the syntax that would allow you to do so.

Upvotes: 9

GoZoner
GoZoner

Reputation: 70185

Define an init() method as:

init () {
  super.init()
  x = "y"
}

You'll want any other initializers in Obj1 to invoke this as self.init(). The Apple documentation has a long discussion on designated initializers and inheritance vis-a-vis initializers.

Upvotes: 3

Related Questions