I do certainly agree that 5 access levels are _plenty_, C++ “friend” is no 
great friend to me, and I too not want to see another one access level added. 
However, I do think there’s a related problem here worth solving.

Sometimes, trying to break apart a large type using extensions, I encounter 
this pattern:

class Thingamer {
    private var doodads: [Doodad]

    // All of these use the doodads var:

    public func mangleDoodads() { … }
    public func fungeDoodads() { … }
    public func renoberateDoodads() { … }
    private func doodadHelper() { … }

    // …and no other methods touch it
}

My first instinct in this situation is to pull all the doodad-related stuff 
into a separate type, but sometimes that’s the wrong solution. Perhaps the 
public API gets messy or nonsensical if those public doodad-related methods 
aren’t on Thingamer. Perhaps other Thingamer methods use those doodad methods, 
even if they don’t use the private var. Perhaps there’s still coupling to 
Thingamer through other class properties. And so forth.

It would be great to group all the doodad-stuff into an extension. The 
inability of extensions to use class-private vars is the barrier. My usual 
solution is to make the doodads var internal, and then try to remember not to 
use it outside of the extension — which looks a lot like “fake friend”.

It would be nice if Swift extensions let us encapsulate state+behavior 
relationships without having to create new type boundaries.

IIRC, there was talk of extensions being able to add properties to an existing 
type. It seems like this would be feasible, at least for types within the same 
module? Perhaps there’s another better way?

Cheers,

Paul

> On Sep 10, 2016, at 11:28 AM, Xiaodi Wu via swift-evolution 
> <[email protected]> wrote:
> 
> Agreed.
> 
> Swift's access levels are deliberately defined in terms of contiguous blocks 
> of written code [this is inelegantly phrased, but I think you see what I 
> mean]. As such, neither a "class scoped" level nor a level shared between a 
> type and its extensions would fit in such a scheme.
> 
> Such an addition would fundamentally counter the existing design of Swift, 
> open the door for compensating features such as "friend classes" that (IIUC) 
> were deliberately avoided, and fails to compose with existing access levels 
> as inevitably there will be proposals to do. By that I mean, why should a 
> "class scoped" member always be limited in visibility to the same module? 
> This satisfies your particular motivating use case, but someone else will 
> want the same kind of class scoping but also allow a member to be accessed by 
> extensions outside the module (classpublic, if you will); still others will 
> want a member to be overridable outside the module (classopen); for good 
> measure, some will want access limited to only extensions and not other types 
> in the same file (classfileprivate; it is not out of the question for someone 
> to raise this point, since it is a close cousin of the argument for 
> distinguishing private and fileprivate).
> 
> If I had my druthers, it'd be nice to have exactly something like Nevin's 
> idea, a terse way to group related files into submodules, and a keyword like 
> `subinternal` that restricts visibility to that group of files. It would 
> satisfy the motivating use case here while preserving the deliberate design 
> decision that Swift access levels do not pick and choose non-contiguous 
> chunks of multiple files.
> 
> In any case, let's postpone this discussion until it comes into scope at a 
> later phase of Swift evolution. The core team and other experts would no 
> doubt have much to contribute at that time.
> 
> 
> On Sat, Sep 10, 2016 at 09:31 Nevin Brackett-Rozinsky via swift-evolution 
> <[email protected] <mailto:[email protected]>> wrote:
> Indeed, I find it rather less convenient to write “fileprivate” in many 
> places I previously would use “private”, and unfortunate that I must choose 
> between aggregating many pieces into a single lengthy file or else polluting 
> the module scope with implementation details.
> 
> I agree with Xiaodi that submodules are a far cleaner design, and I would 
> very much like to replace “fileprivate” with a short word that implies 
> “private to the submodule”. Then by default each file could be its own 
> submodule, and a developer could opt into having more files in a submodule if 
> they so desire.
> 
> Count me as opposed to any sort of “class scoped” access level.
> 
> Nevin
> 
> 
> 
> On Sat, Sep 10, 2016 at 10:01 AM, Rien via swift-evolution 
> <[email protected] <mailto:[email protected]>> wrote:
> > On 10 Sep 2016, at 14:16, T.J. Usiyan via swift-evolution 
> > <[email protected] <mailto:[email protected]>> wrote:
> >
> > I am firmly against this. The 5 levels that we have cover us well and have 
> > enough complexity already.
> 
> Agree.
> 
> 
> 
> > On Sat, Sep 10, 2016 at 5:23 AM, Tom Bates via swift-evolution 
> > <[email protected] <mailto:[email protected]>> wrote:
> > I agree that classprivate would probably not work, maybe constructprivate? 
> > but then you are leaving our enum etc.
> > With the `internal(class)` suggestion, if declaring a var such as 
> > `internal(set) var name: String?` would this become `internal(class, set) 
> > var name: String?`
> > Also there would need to be some kind of compile check either way because 
> > if you declared an enum for example outside of a constructor you would not 
> > be able to mark it as our new constructor only access level or it would 
> > become inaccessible throughout the project.
> >
> > Re: submodules, they are indeed overkill for this. As you would need a 
> > separate submodule for each class you wanted to do this with and then run 
> > the risk of inter coupling lots of different really small submodules.
> >
> > Suggestions so far:
> > `classprivate`
> > `constructprivate`
> > `private(instance)`, `private(instance, set)` - problem -> how would this 
> > work? `public private(instance, set)`
> > `internal(class)`
> >
> > Personally I think a name like `classprivate` or `constructprivate`, 
> > although not particularly well named would reduce complexities with private 
> > setters syntax and keep migrations much simpler.
> >
> >
> > On Sat, 10 Sep 2016 at 07:09 Adrian Zubarev via swift-evolution 
> > <[email protected] <mailto:[email protected]>> wrote:
> > I don't think submodules would solve it nicely. Each module/submodule will 
> > require it's own namespace + it feels like an overkill to create submodules 
> > for a few types. `internal(xyz)` seems to me like a better solution. And 
> > yes this is purely additional and nothing for phase 1.
> >
> > --
> > Adrian Zubarev
> > Sent with Airmail
> > Am 9. September 2016 um 19:09:12, Xiaodi Wu ([email protected] 
> > <mailto:[email protected]>) schrieb:
> >
> >> Isn't the general solution to this problem submodules? In any case, seems 
> >> like it'd be out of scope for Swift 4 phase 1.
> >>
> >>
> >> On Fri, Sep 9, 2016 at 11:34 AM, Adrian Zubarev via swift-evolution 
> >> <[email protected] <mailto:[email protected]>> wrote:
> >> There must be a better solution to this problem, because you might also 
> >> extend value types from different files. That would mean, we'd need 
> >> `structprivate` `protocolprivate` etc.
> >>
> >> How about: `internal(class)` etc. ? Or something like `internal(private)` 
> >> to rule them all (I don't like the last name, but something that would 
> >> rule them all would be nice to have)!
> >>
> >>
> >> --
> >> Adrian Zubarev
> >> Sent with Airmail
> >> Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution 
> >> ([email protected] <mailto:[email protected]>) schrieb:
> >>
> >>> There is currently no way of accessing "shared code" from extensions 
> >>> declared outside the base .swift file
> >>>
> >>> I would love to see along side the new fileprivate access level a 
> >>> classprivate access level that would allow any extension declared outside 
> >>> of the original .swift file to access these properties and functions in 
> >>> an attempt to reuse code.
> >>>
> >>> an example is below...
> >>>
> >>> =================
> >>> //MyClass.swift
> >>> public class MyClass {
> >>>
> >>> classprivate func sharedFunction() {
> >>>   self.function1()
> >>>   self.function2()
> >>> }
> >>>
> >>> fileprivate func function1() {}
> >>> fileprivate func function2() {}
> >>> }
> >>> =================
> >>>
> >>> =================
> >>> //MyClass+Save.swift
> >>> extension MyClass {
> >>>
> >>> public func save() {
> >>>   self.someFunction()
> >>>   self.sharedFunction()
> >>> }
> >>>
> >>> fileprivate func someFunction() {}
> >>> }
> >>> =================
> >>>
> >>> Currently to achieve anything like this you would have to make the "core" 
> >>> functions public or internal or write the whole thing in a single file 
> >>> which as I understand it is not optimal for the compile speed and can get 
> >>> unmanageable for large classes. This would allow a more managed file 
> >>> structure and the separation of related functions from the core 
> >>> declaration.
> >>>
> >>> There would be no migration needed I don't think as the impact on current 
> >>> code would be zero until the developer adopts the new access level
> >>>
> >>> Regards,
> >>> Tom
> >>> _______________________________________________
> >>> swift-evolution mailing list
> >>> [email protected] <mailto:[email protected]>
> >>> https://lists.swift.org/mailman/listinfo/swift-evolution 
> >>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> >>
> >> _______________________________________________
> >> swift-evolution mailing list
> >> [email protected] <mailto:[email protected]>
> >> https://lists.swift.org/mailman/listinfo/swift-evolution 
> >> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> >>
> >>
> > _______________________________________________
> > swift-evolution mailing list
> > [email protected] <mailto:[email protected]>
> > https://lists.swift.org/mailman/listinfo/swift-evolution 
> > <https://lists.swift.org/mailman/listinfo/swift-evolution>
> >
> > _______________________________________________
> > swift-evolution mailing list
> > [email protected] <mailto:[email protected]>
> > https://lists.swift.org/mailman/listinfo/swift-evolution 
> > <https://lists.swift.org/mailman/listinfo/swift-evolution>
> >
> >
> > _______________________________________________
> > swift-evolution mailing list
> > [email protected] <mailto:[email protected]>
> > https://lists.swift.org/mailman/listinfo/swift-evolution 
> > <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected] <mailto:[email protected]>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected] <mailto:[email protected]>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to