Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: access level between `private` and `internal`?

In my Swift code, I often use the private modifier to limit the visibility of helper classes. For example, in one file, I'll have a GridController and a GridControllerModel.

The GridController (the UI) should be accessible to the rest of the application, but the model class is wholly internal and should never be accessed by the rest of the application.

I can address this in Swift by making both classes private and keeping them in the same file. But this gets unwieldy as classes get bigger. What I'd like to do is keep each class in a separate file (for programming convenience), but prevent access to the model class anything but GridController (for information hiding purposes).

Is there any way to do this in Swift?

like image 616
Bill Avatar asked Oct 18 '22 13:10

Bill


1 Answers

As others have said, there is no way to do exactly what you want today in Swift.

One alternative is to use an extension in another file to add GridControllerModel as a nested subtype of GridController. e.g.

//GridControllerModel.swift

extension GridController {
    struct GridControllerModel {
        let propertyOne:String
        let propertyTwo:String
    }
}

This allows your GridController class in its own separate file to declare something like:

var model = GridControllerModel()

However, the rest of the application can still access the GridControllerModel type like this:

//SomeOtherClass.swift

var nested = GridController.GridControllerModel()

So, you do achieve some separation by making the model type a subtype of GridController, but it isn't true access control. On the plus side, it will not appear in code completion outside of the GridController class as "GridControllerModel", you would need to first type "GridController" and then "." to see the subtype "GridController.GridControllerModel"

It's also worth noting that an additional access control level is currently under review and likely to be in the next version of Swift (3.0) :

https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md

Assuming this proposal is accepted and implemented, you would be able to update your declared subtype like this:

//GridControllerModel.swift

local extension GridController {
    struct GridControllerModel {
        let propertyOne:String
        let propertyTwo:String
    }
}

(Note the "local" keyword above now). This would make the GridControllerModel type invisible and inaccessible to all classes except GridController and any extensions of GridController.

So, I would recommend that you consider this nested subtype approach today, because when Swift 3.0 arrives later this year, it's likely to support what you want by simply adding a keyword in front of your subtype declaration. And in the meantime, you get some of the separation you want as well.

like image 188
Daniel Hall Avatar answered Oct 21 '22 11:10

Daniel Hall