[swift-evolution] private & fileprivate

Xiaodi Wu xiaodi.wu at gmail.com
Sat Oct 8 15:33:55 CDT 2016

On Sat, Oct 8, 2016 at 3:24 PM, Karl <razielim at gmail.com> wrote:

> On 8 Oct 2016, at 21:01, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> On Sat, Oct 8, 2016 at 12:02 PM, Karl via swift-evolution <swift-
> evolution at swift.org> wrote:
>> On 8 Oct 2016, at 16:47, Braeden Profile <jhaezhyr12 at gmail.com> wrote:
>> On Oct 8, 2016, at 6:58 AM, Karl via swift-evolution <
>> swift-evolution at swift.org> wrote:
>> I was thinking that the domains themselves could be associated with a
>> domain, so you could create alternate domains which are also
>> publicly-visible, but distinct from the default, “public” domain.
>> For example, if you have a bunch of methods which should be visible to
>> subclasses, but you don’t want them to clutter your regular interface.
>> Perhaps they have names which are confusingly-similar to the public API. I
>> believe that is what “protected” is typically used for.
>> Yes, but “protected" was specifically put down by the core team, seeing
>> that any code from outside the library should see the class as one
>> well-designed whole, not something with complicated, visible implementation
>> details.  If your class-internal methods are confusing (and aren’t
>> necessary for normal use), they shouldn’t be made public in any way.
>> Subclasses would too easily confuse the distinction between your
>> implementation methods and your public ones.
>> For what it’s worth, I was only confused by “private” and “fileprivate”
>> for a minute or two until I looked up the actual proposal.  I haven’t had
>> trouble with it, and it does actually provide more flexibility for code
>> access at the file level than we had before.  Even if the syntax is clunky.
>> I’m not saying that (file)private is confusing - it’s very clear about
>> what it does. But it is limiting; anything that wants access to those
>> semi-private details needs to live in the same file. That’s clearly not
>> scalable. Enormous files many thousands of lines long are easy for the
>> compiler to digest, but less easy for humans to understand and navigate. In
>> fact, I believe this whole “file-based” access control originally came out
>> of the compiler’s implementation details.
> I'm interested in more information about this. What sorts of code have you
> been writing where a file would have to be thousands of lines long in order
> to accommodate `fileprivate`? Many entire modules are only thousands of
> lines long--is there a reason this code couldn't be refactored into a
> module of its own? As mentioned by Matthew, isn't this calling for some
> notion of submodules?
> The tab controller was one example:
> - final class TabController : UIViewController
> - final class TabControllerView : UIView
> - final class Tab : UIView
> All of these required knowledge of semi-private implementation details of
> each-other due to the API I wanted to achieve. I wasn’t interested in
> factoring out the interfaces in to protocols because they’re all final
> classes and only supposed to be used with each other. For example,
> Tab.close() called a fileprivate function in TabController to actually
> close the tab given an instance of the underlying TabItem data structure.

That's interesting. And if you put all the uses of `fileprivate` members of
TabController in the same file, that file would be thousands of lines long?
Have you explored options where you nest types (e.g. `TabController.View`,
which would be able to access private members of `TabController`?)

In that case, submodules wouldn’t really help. I could technically define
> the TabController as a submodule and use “internal”, but that’s also much
> less than optimal. I want to expose a handful of functions to a handful of
> other types (and not expose those functions anywhere else - e.g. from my
> module-internal UIViewControllers which happen to contain a TabController).
> Also, how would I expose things from the TabController module to the outer
> module without making it fully "public”?

If you want to expose only a handful of functions to a handful of other
types, it sounds like that would be a good use case for `fileprivate` that
would result in a very readable file, no?

> What it would basically come down to is that the interface of the object
>> would be separated in to blocks based on your access privileges. When
>> viewing the interface, it wouldn’t look much different to an extension:
>> *access(public)* class TabController {
>>    var tabs : [Tab] { get }
>>    func closeTab(at: Int)
>> }
>> *access(TabBarStuff)* extension TabController {
>>     func close(tab: Tab)
>> }
>> I definitely want something between internal and fileprivate, at least. I
>> don’t see any reason at all why objects shouldn’t be allowed to present
>> optional “slices” of their interface to appropriate clients. In fact, that
>> is what access control is all about. I just want to generalise it to allow
>> for user-defined visibility scopes (as well as the default ones for public,
>> module, file and scope). That leads to the question of what visibility
>> those user-defined scopes would have; and if you leave them entirely open
>> to adopt any scope (except themselves), then you end up with the ability to
>> slice your API for different use-cases. Or we could be boring and limit
>> them to the module they are defined in.
>> The whole reason I’m bringing this up is because I don’t like the “file”
>> part of fileprivate. How I split my files up is a readability decision.
>> Karl
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161008/8ac4e3df/attachment.html>

More information about the swift-evolution mailing list