Initializer is inaccessible due to 'private' protection level

Hi,

I am not sure why the compilation error initializer is inaccessible due to 'private' protection level is thrown

struct Car {
    var name: String
    private var price = 0 //changing it to let or making it internal fixes the issue
}

let car = Car(name: "aaa") //'Car' initializer is inaccessible due to 'private' protection level

Question:

Wouldn't the compiler be able to detect that in all execution flows price would be initialised and therefore be able to synthesise the default initialiser?

1 Like

price is private, so the synthesized member-wise initializer for Car is private. Therefore, you can't call it from outside the type. I'm not sure how your comment about "execution flows" applies here.

The synthesized member-wise initializer is:

init(name: String, price: Int = 0)
2 Likes

@Peter-Schorn Thank you so much for the clear explanation

But it seems to work when it is private let.

So what happens in private let that is different from private var?

A private let with an initializer doesn't need to be a parameter in the synthesized init.

2 Likes

When an instance property is declared as a let constant and contains an initialization expression (in your case, 0), it does not appear in the synthesized initializer. Furthermore, it is not possible to set this property in any initializer, because initialization expressions are executed before the body of the initializer.

1 Like

@Avi Thank you so much for explaining that

@Peter-Schorn I think the following makes it even more clear

Furthermore, it is not possible to set this property in any initializer, because initialization expressions are executed before the body of the initializer.

Please bear with me as (I am a bit slow to understand) I have one bit, wouldn't private var also be initialised using the initialization expressions?

The difference is that a var can be changed (such as by the synthesized init). A let can only be initialized once, so properties which include an initialization in their declaration can't be changed, not even by init.

3 Likes

Yes, but because it is mutable, you can assign another value to it in the body of an initializer.

When an instance property does not appear in the member-wise initializer—for reasons I explained above—its access level has no effect on the access level of the initializer.

2 Likes

@Avi @Peter-Schorn

Thank you so much guys, the last round of explanations sealed it for me, I understand much better, thank you so much for patiently answering my repeated questions.

1 Like

You just need to create your own init and it will solve your problem

init(name: String) {
   self.name = name
}