Initialized Twice?

Hi. This is from the Apple's Swift 4.2 book.


In line 02, numberOfSides was already initialized to 0. Why does numberOfSides still need to be initialized in line 19 when it already has an initialized value of 0?



class NamedShape {
    var numberOfSides: Int = 0
    var name: String

    init(name: String, numberOfSides: Int) {
       self.name = name
    }

    func simpleDescription() -> String {
       return "A shape with \(numberOfSides) sides."
    }
}

class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name, numberOfSides: 1)
        //numberOfSides = 3
    }

    var perimeter: Double {
        get {
             return 3.0 * sideLength
        }
        set {
            sideLength = newValue / 3.0
        }
    }

    override func simpleDescription() -> String {
        return "An equilateral triangle with sides of length \(sideLength)."
    }
}


Thank you.

God bless, Proverbs 31

Accepted Reply

Isn't it the same question as


https://forums.developer.apple.com/thread/112587


The initialization with value of 0 at line 2 is just to have some value in the property (required by compiler) ; otherwise, you need to write it in an init(), or declare as optional.


So this value is not to be used, it will always be replaced when you instanciate an instance.

You have a convenience initializer that let you define the value to use for the instance.


That's what you do on line 19.


Note the sequence

class EquilateralTriangle: NamedShape { 
    var sideLength: Double = 0.0 
 
    init(sideLength: Double, name: String) { 
        self.sideLength = sideLength 
        super.init(name: name, numberOfSides: 1) 
        //numberOfSides = 3 
    }


1. Line 2 declares a property.

All properties defined in the class must be set before you call super.init.

Here it is done twice : by declaring = 0.0

and by setting the value before super.

But, if you simply wrote

var sideLength : Double

and call super first

class EquilateralTriangle: NamedShape {
     var sideLength: Double
    
     init(sideLength: Double, name: String) {
          super.init(name: name, numberOfSides: 1)
          self.sideLength = sideLength
     }


You would get a compiler error

Property 'self.sideLength' not initialized at super.init call


2. Line 6 calls the convenience initializer,

to set name and numberOfSides. This is an initializer defined in superClass, so need to call super.init


3. You could add a direct setting for the property at line 7:

self.numberOfSides = 3


The subclass inherits its numberOfSides property from its super class, so you can use self.

But you could also set it in the superclass (of the instance you create) by calling

super.numberOfSides = 3


Note: this code is just for illustration, as a triangle has 3 sides, not 1.

Replies

Isn't it the same question as


https://forums.developer.apple.com/thread/112587


The initialization with value of 0 at line 2 is just to have some value in the property (required by compiler) ; otherwise, you need to write it in an init(), or declare as optional.


So this value is not to be used, it will always be replaced when you instanciate an instance.

You have a convenience initializer that let you define the value to use for the instance.


That's what you do on line 19.


Note the sequence

class EquilateralTriangle: NamedShape { 
    var sideLength: Double = 0.0 
 
    init(sideLength: Double, name: String) { 
        self.sideLength = sideLength 
        super.init(name: name, numberOfSides: 1) 
        //numberOfSides = 3 
    }


1. Line 2 declares a property.

All properties defined in the class must be set before you call super.init.

Here it is done twice : by declaring = 0.0

and by setting the value before super.

But, if you simply wrote

var sideLength : Double

and call super first

class EquilateralTriangle: NamedShape {
     var sideLength: Double
    
     init(sideLength: Double, name: String) {
          super.init(name: name, numberOfSides: 1)
          self.sideLength = sideLength
     }


You would get a compiler error

Property 'self.sideLength' not initialized at super.init call


2. Line 6 calls the convenience initializer,

to set name and numberOfSides. This is an initializer defined in superClass, so need to call super.init


3. You could add a direct setting for the property at line 7:

self.numberOfSides = 3


The subclass inherits its numberOfSides property from its super class, so you can use self.

But you could also set it in the superclass (of the instance you create) by calling

super.numberOfSides = 3


Note: this code is just for illustration, as a triangle has 3 sides, not 1.

Once again, the code you have shown is not the same as in the Apple's Swift 4.2 book.


Why have you added the initialization where Swift compiler does not claim to be needed?

Hi. You're right, Disregard, sorry. I guess the original code did not comment out line 20.

Hi. Thanks again for the reply. I checked again, you're right. Line 20 which is not commented out, line 19 and line 05 which doesn't have the numberOfsides prameter in the original- sorry. (I should put a comment where I changed it when I experiement so I don't get perplexed when I get back to it a few weeks later.)

By the way, why didn't the Apple/Swift creators not include an automatic memberwise initializer for the classes (like how it is, in structs)? Is there an advantage of not having a the memberwise initializer as default/implicit? Not having it implicitly makes the code longer and prone to error- it's more of a disadvantage, it seems.

Maybe you should visit forums.swift.org. And/or read the Deferred proposal SE-0018, especially its Rationale.

github.com/apple/swift-evolution/blob/master/proposals/0018-flexible-memberwise-initialization.md


I do not understand why such a huge and complex compiler magic like Codable can be accepted but memberwise initializer for class cannot. But currently this is not a good place to say something to the designers of Swift.