Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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'

like image 413
Patrick Perini Avatar asked Jun 09 '14 14:06

Patrick Perini


People also ask

What is the default value of instance variable?

An instance variable can also be a variable of object type. For such variables, the default initial value is null. (In particular, since Strings are objects, the default initial value for String variables is null.)

Are instance variables initialized to a default value yes or no?

Yes, it does have 0.0 as a default value. All primitive types ( int , double , ...) will be initialized to 0 and all reference to other types (somehow extending Object ) will be initialized to null .


3 Answers

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.

like image 154
Erik Avatar answered Nov 04 '22 09:11

Erik


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.

like image 31
Chris Conover Avatar answered Nov 04 '22 08:11

Chris Conover


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.

like image 25
GoZoner Avatar answered Nov 04 '22 08:11

GoZoner