Private var is accessible from outside the class
Asked Answered
H

2

33

This was done in Playground, just to simplify.

class MyPrivateVar
{
    private var priv: String?
}

var myInstance = MyPrivateVar()

myInstance.priv = "Something"

No compiler warning. In fact auto-complete is showing priv without a problem. My understanding is that outside the boundaries of {} of the class, I'm not supposed to be able to see a private anything, func nor var.

Am I missing something?

Houseman answered 28/9, 2014 at 17:15 Comment(1)
adding tag swift2 as this is no longer true in swift3Supine
T
48

Access modifiers in Swift are implemented differently than other languages. There are three levels:

private: accessible only within that particular file

internal: accessible only within the module (project)

public: accessible from anywhere

Unless marked otherwise, everything you write is internal by default.

The Swift blog had a post about access control when the features were introduced in beta 4, and Apple's documentation has a chapter as well.

Ternan answered 28/9, 2014 at 18:14 Comment(3)
"Private access restricts the use of an entity to its own defining source file. Use private access to hide the implementation details of a specific piece of functionality.". I guess when they say 'file' they actually mean it. It does not make too much sense to have a private scope restricted not to own class, but to the physical file it's in. I guess having classes in the same file is not just convenience, it has functional meaning. Maybe has something to do with 'private' headers not copying outside.Houseman
The blog post linked in the answer goes into some of their reasons for this non-standard system, and they have another post on why they didn't include "protected" that goes into more detail.Ternan
In Swift 3, this will change so private limits the declaration to the current scope and fileprivate (the new access modifier) will do what private was doing before Swift 3. This article has a good summary of the access modifiers in Swift 3.Carrero
P
8

Note: this answer is for Swift 2


The Swift Programming Language states:

Swift provides three different access levels for entities within your code. These access levels are relative to the source file in which an entity is defined, and also relative to the module that source file belongs to.

If you wan't to test private access level with Swift, the following step by step may help you.

1/ Create a new Xcode project.

2/ Create a file, MyPrivateVar.swift, and add the following code in it:

class MyPrivateVar {

    private var priv: String? = nil

}

3/ Create a second file, MySecondClass.swift, and add the following code in it:

class MySecondClass {

    init() {
        var myPrivateVar = MyPrivateVar()
        myPrivateVar.priv = "some string"
    }

}

Xcode will immediatly give you a Swift compiler error message:

'MyPrivateVar' does not have a member named 'priv'

4/ Now, remove the two previous files from your project and create a single file TwoClassesInAFile.swift with the following code in it:

class MyPrivateVar {

    private var priv : String? = nil

}

class MySecondClass {

    init() {
        var myPrivateVar = MyPrivateVar()
        myPrivateVar.priv = "some string"
    }

}

This time, you will get no Swift compiler error message and you will be able to access MyPrivateVar's priv private property from MySecondClass because priv and MySecondClass are in the same file (your TwoClassesInAFile.swift file).

Furthermore, access levels also work for global variables. For example, Xcode won't give any compiler error if the following code is part of the same ViewController.swift file:

import UIKit

private var globalPrivate : String? = nil

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        globalPrivate = "some string"
        println(globalPrivate)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

However, if you define globalPrivate outside of ViewController.swift, Xcode will generate an error message:

Use of unresolved identifier 'globalPrivate'

Plaice answered 28/9, 2014 at 21:0 Comment(2)
Was using Playground simply to double check. Original problem took place on a view controller file in a project. I noted that I was using Playground to simplify issue.Houseman
Point number 4 is wrong in swift 3 and xcode 8. class AccessModifiersClass { private var privV : String? internal var inteV : String? public var publV : String? var defV : String? } class CheckPoint { init() { globalPrivate = "some string" let lVar = AccessModifiersClass() lVar.priv = "Public" lVar.inteV = "Internal" lVar.publV = "Public" lVar.defV = "default" } }Meade

© 2022 - 2024 — McMap. All rights reserved.