[swift-evolution] Class scoped access level

Xiaodi Wu xiaodi.wu at gmail.com
Sat Sep 10 14:52:14 CDT 2016


Is that (i.e. having properties in extensions) listed in the completing
generics manifesto? It certainly seems like it'd be a worthwhile feature to
consider under that umbrella.

The one place where it will complicate matters is in the use of protocol
extensions as traits, since what I know of traits is that they should not
encapsulate state.


On Sat, Sep 10, 2016 at 14:13 Paul Cantrell <cantrell at pobox.com> wrote:

> 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 <
> swift-evolution at swift.org> 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 <
> swift-evolution at swift.org> 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 <
>> swift-evolution at swift.org> wrote:
>>
>>> > On 10 Sep 2016, at 14:16, T.J. Usiyan via swift-evolution <
>>> swift-evolution at swift.org> 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 <
>>> swift-evolution at swift.org> 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 <
>>> swift-evolution at swift.org> 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 (xiaodi.wu at gmail.com)
>>> 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 <
>>> swift-evolution at swift.org> 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 (
>>> swift-evolution at swift.org) 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
>>> >>> swift-evolution at swift.org
>>> >>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> >>
>>> >> _______________________________________________
>>> >> swift-evolution mailing list
>>> >> swift-evolution at swift.org
>>> >> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> >>
>>> >>
>>> > _______________________________________________
>>> > swift-evolution mailing list
>>> > swift-evolution at swift.org
>>> > https://lists.swift.org/mailman/listinfo/swift-evolution
>>> >
>>> > _______________________________________________
>>> > swift-evolution mailing list
>>> > swift-evolution at swift.org
>>> > https://lists.swift.org/mailman/listinfo/swift-evolution
>>> >
>>> >
>>> > _______________________________________________
>>> > swift-evolution mailing list
>>> > swift-evolution at swift.org
>>> > https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
> _______________________________________________
> 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/20160910/8d5dd39b/attachment.html>


More information about the swift-evolution mailing list