Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift do subclasses inherit initializers? [duplicate]

I have the following code:

class Parent {

    var foo: Int

    init(someNum: Int) {
        self.foo = someNum
    }
}

class Child: Parent {

}

var parent = Parent(someNum: 999)
println(parent.foo)                  // prints "999"

var child = Child(someNum: 3872)   
println(child.foo)                   // prints "3872"

In Apple's 2014 WWDC "Intermediate Swift" video, he says that initializers aren't inherited by default unless there is a default value for it's stored properties. However there is no default value for foo in the subclass Child but it clearly inherits the init(someNum:) method. Am I understanding the explanation wrong or is there something else going on?

like image 465
somtingwong Avatar asked Jul 16 '15 15:07

somtingwong


1 Answers

From the Apple docs:

Subclasses do not inherit their superclass initializers by default. However, superclass initializers are automatically inherited if certain conditions are met. In practice, this means that you do not need to write initializer overrides in many common scenarios, and can inherit your superclass initializers with minimal effort whenever it is safe to do so.

Assuming that you provide default values for any new properties you introduce in a subclass, the following two rules apply:

Rule 1 If your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers.

Rule 2 If your subclass provides an implementation of all of its superclass designated initializers—either by inheriting them as per rule 1, or by providing a custom implementation as part of its definition—then it automatically inherits all of the superclass convenience initializers.

These rules apply even if your subclass adds further convenience initializers.

In your case, you did not provide any designated initializer in Child. Therefore, the only one designated initializer has been inherited from Parent.

If you modify the Child class to:

class Child : Parent {
  var age : Int
  init (age : Int) {
     self.age = age
    super.init(foo: 10)
  }
}

You will see that you cannot create a Child class by calling its superclass initializer. Read more.

EDIT:

The rules above apply to a more different scenario. Maybe the docs are a little bit confusing for you, but let's just pause and think for a moment. You have a subclass which inherits from a superclass which has one property foo. Now, if your subclass does not add any properties, or adds properties with default values, there is no need for a different initializer than the one from the superclass and so you can safely use it. On the other hand, if you add a property without a default value, you cannot use the initializer from the superclass because the added property needs to be initialized somehow. The compiler will complain and you will have to do one of the two things:

  1. You should implement a designated initializer in the subclass which will assign the new property and also call the designated initializer in the superclass.
  2. You could add a default value to your property and you could still use the designated initializer from the superclass.
like image 81
Teo Avatar answered Sep 28 '22 14:09

Teo