3

While talking about failable initializers, The Swift Programming Language Tutorial by Apple states that unlike value types, for classes, the failable initializer check for nil should come after all stored properties are initialized to a default value. Then, it moves on to suggest defining the stored properties as "implicitly unwrapped optionals" since that kind of a definition would set the stored property to nil by default and satisfy the aforementioned requirement for the failable initializers for classes. Next, it provides the following example to show how this implicitly unwrapped optional thing can be applied:

Example taken from the tutorial (version 2015-9-16)

class Product {
    let name: String!
    init?(name: String) {
        self.name = name
        if name.isEmpty { return nil }
    }
}

To me, there is a logical inconsistency between what is explained in the text and what this example illustrates. In my humble opinion, if we were to understand how defining the name property as a String! makes the failable initializer able to fail at the very beginning of the initialization - by satisfying the class' requirement of setting all stored properties to a default value - then I would expect the orders of the two statements in the init? body to be interchanged as follows:

init?(name: String) {
    if name.isEmpty { return nil }
    self.name = name
}

Only after that, we would understand that the name property, which is defined as String!, already has a default value when the initialization begins (which is nil) and lets it to fail if it is being set to an empty string.

Moreover, I tried interchanging the order of those statements in a playground to see the effect and I got an error stating that "All stored properties should be initialized... etc".

Could you please clarify what's going on here?

Thanks in advance...

Edit:

I do not think that this post is a duplicate. I already read thoroughly the post, which you suggest to be answering the question.

Specifically, I think mustafa's answer is not an explanation to what I am asking. He answers the question of "why we need to initialize all the stored properties of an instance, which is about to return nil through its failable initializer". I acknowledge that this is due to a compiler limitation: Currently, the complier cannot destroy partially initialized class instances when necessary. Hence, they try to avoid conditions in which such instances may occur. So they suggest defining the name property as aString! in the example for instance. Why? Because, that definition will default the name property to nil. So, even if I do not assign any value to the property before trying to assign it to an empty string, the failable initializer will fail since it will consider the name property to be set to a valid value, which is nil.

However, what I say is, their suggestion does not provide the result they aim for. Why do I still get the error of "uninitialized stored property" if I write the statement self.name = name after the isEmpty check? If that suggestion was working, then this would not return any errors. Do I miss something here?

Hope, my question is a little bit clearer now. Thanks...

Omer
  • 39
  • 2
  • 2
    I believe mustafa's answer here explains what's going on: http://stackoverflow.com/a/26497229/19679 . It's a known compiler shortcoming that they have on their list to fix. – Brad Larson Sep 29 '15 at 18:24
  • 1
    I think mustafa's answer is not an explanation to what I am asking. He answers the question of "why we need to initialize all the stored properties of an instance, which is about to return `nil` through its bailable initializer". I acknowledge that this is due to a compiler limitation. However, what I say is, their suggestion of defining the property as a `String!` in the example does not provide the result they aim for. Why do I still get the error of "uninitialized stored property" if I write the statement `self.name = name` after the `isEmpty` check? – Omer Sep 30 '15 at 13:26
  • For `let` properties, you must define an initial value. Optionals default to nil in the `var` case, but you're still going to have to assign an initial value if you use them as `let` properties. This is true even for implicitly unwrapped optionals. The fundamental issue is that the compiler doesn't yet recognize that bailing out early with nil in the initializer makes setting up the properties unnecessary in that code path. – Brad Larson Sep 30 '15 at 14:23
  • Hi Brad, thanks a million for your response! Now it is all clear for me! When I define it as `var`, and use implicitly unwrapped string, I no longer need to say `self.name = name` and get no errors! But in the let case, if I committed that assignment, I was getting the error even if I define it as `String!`. That was the confusion for me but now it is resolved! The the implicit unwrapped property trick works only for the case of a variable stored property then, not for constants.. – Omer Sep 30 '15 at 14:51

0 Answers0