6

The following code works fine

struct carConfi {
    var owner: String?
    let brand: String = "BMW"
    var currentMile: Double = 2000
}

let tomCar = carConfi()

However, if I change the type of the property owner to constant, there will be an error at the initializer

struct carConfi {
        let owner: String? // Change to constant
        let brand: String = "BMW"
        var currentMile: Double = 2000
    }

let tomCar = carConfi() //error: missing argument for parameter 'owner' in call 

I did a bit search, it turns out that it is because the optional variables automatically have a default value of nil

I guess: Because once the constant is set, it then cannot be changed, if the optional constant automatically received an nil then it will keep as an unchangeable nil that's very silly and may against the users will

Question: My college doesn't fully convinced by the guess, he told me there must be more reasons for that. I would very appreciate if someone can explain that to me

Thx

SLN
  • 4,772
  • 2
  • 38
  • 79
  • Your guess is right. What possible use case would there be for defaulting a `let` value to `nil`? But it is a very likely mistake, so having an error there is certainly helpful. – Rob Napier May 23 '16 at 20:52
  • You can boil this example down to `let foo:String?; print(foo)` vs `var foo:String?; print(foo)` btw. – Hamish May 23 '16 at 20:55

2 Answers2

6

Not setting a read-only (constant) field with either an:

  • initialization expression
  • initializer

is almost certainly an indication of an error in your program.

Since you have no other opportunity to set the value of your let field, the value of the field is going to remain nil (or some other default). It is rather unlikely that a programmer would find such behavior desirable, and request it on purpose.

That is why Swift marks this situation as an error. On the other hand, if you actually wanted your String constant to remain nil, you could add an expression to set it to nil, and silence the error:

let owner: String? = nil // Pretty useless, but allowed
mfaani
  • 33,269
  • 19
  • 164
  • 293
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • It doesn't seem unreasonable for *certain* initializers to set the value, and for others to ignore the property (and have it set to the default of `nil`). The mentioned `let owner: String? = nil` wouldn't allow this behavior either. – pkamb Jan 22 '17 at 00:02
  • `let`s that default to nil would allow for a subclass to inherit its superclass's initializers. Using `var` allows this. But add a `let` to a subclass and you then need to override the superclass initializers. – pkamb Jan 22 '17 at 00:07
  • I completely understood your answer, I just understand your terminology. what do you mean by *initialization expression* you mean `String? = nil`? and by *initializer* you mean `init (owner: String){ self.ownder = ownder}` ? – mfaani Feb 09 '17 at 17:45
  • @Honey Correct, initialization expression is what follows `=` in `let owner: String? = nil`. In this case, initialization expression is `nil`, and initializaer is any overload of `init`. – Sergey Kalinichenko Feb 09 '17 at 17:53
3

Constants are set once, and once only. If you wanted it to be null or 0, then you would set it. You always define a constant on initiation.

JohnV
  • 285
  • 1
  • 3
  • 13