Type-based ‘private’ access within a file


(Paweł Wojtkowiak) #1

Maybe a better solution would be allowing to write a type extensions within its lexical scope (I already saw similar proposition earlier on SE by someone else but I think it disappeared at some point). This would eliminate problems with changing access levels, no migration needed and would not hurt submodules in any way if they come to life later.
Example:

protocol SomeDelegateProtocol {
  func didFire()
}

struct MyStruct {
  private var x = 5

  extension Self: SomeDelegateProtocol {
  func didFire() {
      x += 5 // allowed
    }
  }
}

This would be in line with the proposal where Self keyword would be introduced to classes and structs.
I think this would be simple enough to write, probably not too difficult to implement, and would still allow to group protocol conformances via extensions in a sensible way. Also, it gives the developer freedom about whether they want to use private more strictly (they would just declare extensions as they did now) or if the extensions are tightly related to the type that they need to access private members - they could use this solution.

extension Self... part could be spelled differently if the community and/or core team feels like there are better options to this.

Just a little thought from me after reading the most recent discussions. If this proposal turns out to be a bad idea for some reason, I'd indeed prefer a type scoped 'private' than what is available currently in Swift 3. Managing privates and fileprivates is a pain, and I just want to be able to group my code in some way, especially when it comes to protocol conformance.

Wysłane z iPhone'a

···

Dnia 05.04.2017 o godz. 18:54 Nevin Brackett-Rozinsky <nevin.brackettrozinsky@gmail.com> napisał(a):

On Wed, Apr 5, 2017 at 12:02 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

- fileprivate should really become much more rare, which makes it more meaningful and significant where it occurs. This was the original idea and intent behind SE-0025.

I would like to understand the reasoning here. I just looked back at SE-0025 and I see this same assertion, but I cannot find the reasoning. Could you explain it to me please?

Certainly I would love to make the *spelling* of “fileprivate” be entirely nonexistent. But all the lines of logic I have come up with lead inexorably to the conclusion that the *semantics* of “fileprivate” should be the common, de facto, access level that people reach for when they need encapsulation.

1. Someone makes a file with a single type in it, and marks the implementation details “private”. At this point, it does not matter matter which meaning “private” has, they all work the same so far.

2. The developer adds a free function to the file. Or an extension of another type. Or another type entirely. And they put it in the same file because it needs to work with the implementation details of the existing type.

Now the difference between possible meanings of “private” matters. And if it is anything short of “fileprivate”, then the developer has to go back and change access levels. Things no longer “just work”.

The alternative scenario is that one adds something to the file which doesn’t need privileged access to what’s already there. In which case the questions are, “Why put it in the same file at all?” and “If there is a good reason to put it in the same file, is there any *harm* in it being able to see private members?”

Most developers most of the time should not have to think about sub-file-level granularity. If things are in the same file it is because they need to work together closely. We should be able to mark members “private” and work with them across the file. This dramatically reduces the cognitive burden, and the amount of time spent fiddling with access levels.

With any meaning of “private” less than “fileprivate”, developers end up marking things “private”, then letting the IDE change it to “fileprivate” when the compiler complains. This tells me that people actually want the semantics of “fileprivate”, and they want it to be spelled “private”.

The main exception, where people truly desire and intend for tighter-than-file encapsulation, is when certain invariants must be preserved, and should not be touched except by dedicated methods. And *that* is the important case worth making unambiguously explicit.

All the talk about calling out cross-type sharing within a file seems superfluous. That is one of the principle reasons for putting multiple types in one file to begin with. But preserving invariants, now *that* deserves a meaningful and significant syntax, ideally something loud that warns developers not to mess with it.

So, why exactly is there a desire to make the semantics of “fileprivate” rare?

Nevin