Swift:“私有”和“内部”之间的访问级别?

Bil*_*ill 6 oop information-hiding access-modifiers swift

在我的 Swift 代码中,我经常使用 private 修饰符来限制辅助类的可见性。例如,在一个文件中,我将有 aGridController和 a GridControllerModel

GridControllerUI)应该可供应用程序的其余部分访问,但模型类完全是内部的,并且永远不应该被应用程序的其余部分访问。

我可以在 Swift 中通过创建两个类private并将它们保存在同一个文件中来解决这个问题。但随着班级规模的扩大,这会变得很笨拙。我想做的是将每个类保存在一个单独的文件中(为了编程方便),但阻止对模型类的任何访问GridController(为了信息隐藏的目的)。

在 Swift 中有什么办法可以做到这一点吗?

Dan*_*all 3

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

var model = GridControllerModel()
Run Code Online (Sandbox Code Playgroud)

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

//SomeOtherClass.swift

var nested = GridController.GridControllerModel()
Run Code Online (Sandbox Code Playgroud)

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
    }
}
Run Code Online (Sandbox Code Playgroud)

(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.