1

I seem to be misunderstanding something about access control modifiers in Swift. Here is my code from a playground:

class Something {
    private (set) var name :String {
    get { return "" }
    set {}
    }
}
var thing = Something();
thing.name = "";

My intuition and experience from other languages tells me that there should be a compiler error on the last line.

The book I'm learning from however states that private means the member being modified is only accessible from the same source file.

Am I safe to assume this scenario would generally be an error in most projects, and this is only because I'm running this code in a playground?

Is the statement that private members can only be accessed from the same source file totally accurate?

Ian Newson
  • 7,679
  • 2
  • 47
  • 80
  • 6
    *"private members can only be accessed from the same source"* is totally accurate for Swift 2. – Swift 3 (Xcode 8 beta 6) changed the meaning of private, compare [What is a good example to differentiate between fileprivate and private in swift3](http://stackoverflow.com/questions/39027250/what-is-a-good-example-to-differentiate-between-fileprivate-and-private-in-swift). – Martin R Aug 24 '16 at 19:18
  • @MartinR Thank you, post your comment as an answer and I'll accept it. – Ian Newson Aug 24 '16 at 19:22
  • 1
    I don't want to repeat existing answers :) – And actually your question is unclear to me. Your last statement is correct, so why do you wonder about it? What do you mean by " this scenario would generally be an error in most projects"? – Martin R Aug 24 '16 at 19:26
  • Also possible duplicate of [Why I can set private field in playground](http://stackoverflow.com/questions/35379133/why-i-can-set-private-field-in-playground) or [Private var is accesible from outside the class](http://stackoverflow.com/questions/26087447/private-var-is-accesible-from-outside-the-class) – Martin R Aug 24 '16 at 19:27

2 Answers2

2

This rule is valid for all versions of Swift 2. It is valid for your example as well, and worked because your setter code is in the same file (if I understand your example correctly) in which the setter was invoked.

The top-level assignment expression thing.name = ""; was allowed because it is running in a playground. Outside playgrounds, this particular top-level assignment would be illegal in most cases (there are exceptions!).


Bonus explanation of what constitutes as "top-level code" and where it is applicable; from the official Swift blog here:

However, top-level code is not allowed in most of your Swift source files. For clarity, any executable statement not written within a function body, within a class, or otherwise encapsulated is considered top-level. We have this rule because if top-level code were allowed in all your files, it would be hard to determine where to start the program.

...

You’ll notice that earlier we said top-level code isn’t allowed in most of your app’s source files. The exception is a special file named “main.swift”, which behaves much like a playground file, but is built with your app’s source code. The “main.swift” file can contain top-level code, and the order-dependent rules apply as well. In effect, the first line of code to run in “main.swift” is implicitly defined as the main entrypoint for the program. This allows the minimal Swift program to be a single line — as long as that line is in “main.swift”.

Vatsal Manot
  • 17,695
  • 9
  • 44
  • 80
1

The book I'm learning from however states that private means the member being modified is only accessible from the same source file.

And your example is accessing it from the same source file. What's the issue?

In Swift 3, private becomes fileprivate, wherein access is allowed anywhere from the same file. private in Swift 3 has the behavior you expect, where access is only allowed within the class/struct/enum itself.

Alexander
  • 59,041
  • 12
  • 98
  • 151