Pre-proposal: "private(extension)" access modifier?


(Austin Zheng) #1

Hi all,

One popular use of extensions is to take the definition of a type (e.g.
MyBigClass) and to split it up over a number of files, grouping related
methods together for increased code comprehensibility. However, access
control makes doing so more difficult: members that are implementation
details and declared as 'private' can't be seen from other files.

I'd like to suggest an access modifier: "private(extension)". This follows
in the spirit of the existing "private(set)" for properties. It would work
in the following way:

- A member declared private(set) would be visible throughout the file
within which it was declared, exactly as if it had been declared "private"
today.
- A member declared private(set) would be visible in any file containing an
extension to the member's type, throughout the entire file.
- This would only work for extensions to types declared within the same
module; it would not be meant as a way to expose impl details to other
modules or application code consuming the module.
- A property in T meant to be only gettable from other files, but settable
from extensions to T in other files, would be declared "private(set,
extension)".

I think this is a reasonably elegant, small-surface-area solution to a
common problem, but I can see some potential objections:

- It adds some complexity to the access control subsystem. Maybe that
subsystem is complex enough as is.
- It might leak implementation details of a type T to code belonging to
another type or global function, residing within the same file as an
extension to T.
- Maybe there might be more elegant ways to improve or extend the access
control subsystem.

Any thoughts?

Best,
Austin


(Félix Cloutier) #2

Maybe it's because I know too much about it, but to me, private(extension) doesn't follow the spirit of private(set).

In Swift, access modifiers are tied to the linker's notion of symbol visibility. Private symbols are accessible only within the current file because they're not exported at all. Internal symbols are accessible only within the module because they don't make it to the public symbol table. When you have private(set), all you're saying is "make the setter private", and this is easy.

In general, your definition of private(extension) makes it identical to internal, except that autocomplete won't be cluttered with private(extension) members in files that don't extend the class. Because of that, I don't think that it adds a lot of technical complexity to access control, but it also makes me think that it might not be worth it.

Since private(extension) can be (ab)used to make any member internal, I wonder if we couldn't fix this with finer-grained autocomplete or something instead.

Félix

···

Le 5 janv. 2016 à 19:59:11, Austin Zheng via swift-evolution <swift-evolution@swift.org> a écrit :

Hi all,

One popular use of extensions is to take the definition of a type (e.g. MyBigClass) and to split it up over a number of files, grouping related methods together for increased code comprehensibility. However, access control makes doing so more difficult: members that are implementation details and declared as 'private' can't be seen from other files.

I'd like to suggest an access modifier: "private(extension)". This follows in the spirit of the existing "private(set)" for properties. It would work in the following way:

- A member declared private(set) would be visible throughout the file within which it was declared, exactly as if it had been declared "private" today.
- A member declared private(set) would be visible in any file containing an extension to the member's type, throughout the entire file.
- This would only work for extensions to types declared within the same module; it would not be meant as a way to expose impl details to other modules or application code consuming the module.
- A property in T meant to be only gettable from other files, but settable from extensions to T in other files, would be declared "private(set, extension)".

I think this is a reasonably elegant, small-surface-area solution to a common problem, but I can see some potential objections:

- It adds some complexity to the access control subsystem. Maybe that subsystem is complex enough as is.
- It might leak implementation details of a type T to code belonging to another type or global function, residing within the same file as an extension to T.
- Maybe there might be more elegant ways to improve or extend the access control subsystem.

Any thoughts?

Best,
Austin
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Austin Zheng) #3

I see your point, and I think it's a good one. I'm don't think this
proposal is worth pursuing further, although I would like some notion of
more flexible access control in the future.

Thanks,
Austin

···

On Tue, Jan 5, 2016 at 5:47 PM, Félix Cloutier <felixcca@yahoo.ca> wrote:

Maybe it's because I know too much about it, but to me, private(extension)
doesn't follow the spirit of private(set).

In Swift, access modifiers are tied to the linker's notion of symbol
visibility. Private symbols are accessible only within the current file
because they're not exported at all. Internal symbols are accessible only
within the module because they don't make it to the public symbol table.
When you have private(set), all you're saying is "make the setter private",
and this is easy.

In general, your definition of private(extension) makes it identical to
internal, except that autocomplete won't be cluttered with
private(extension) members in files that don't extend the class. Because of
that, I don't think that it adds a lot of technical complexity to access
control, but it also makes me think that it might not be worth it.

Since private(extension) can be (ab)used to make any member internal, I
wonder if we couldn't fix this with finer-grained autocomplete or something
instead.

Félix

Le 5 janv. 2016 à 19:59:11, Austin Zheng via swift-evolution < > swift-evolution@swift.org> a écrit :

Hi all,

One popular use of extensions is to take the definition of a type (e.g.
MyBigClass) and to split it up over a number of files, grouping related
methods together for increased code comprehensibility. However, access
control makes doing so more difficult: members that are implementation
details and declared as 'private' can't be seen from other files.

I'd like to suggest an access modifier: "private(extension)". This follows
in the spirit of the existing "private(set)" for properties. It would work
in the following way:

- A member declared private(set) would be visible throughout the file
within which it was declared, exactly as if it had been declared "private"
today.
- A member declared private(set) would be visible in any file containing
an extension to the member's type, throughout the entire file.
- This would only work for extensions to types declared within the same
module; it would not be meant as a way to expose impl details to other
modules or application code consuming the module.
- A property in T meant to be only gettable from other files, but settable
from extensions to T in other files, would be declared "private(set,
extension)".

I think this is a reasonably elegant, small-surface-area solution to a
common problem, but I can see some potential objections:

- It adds some complexity to the access control subsystem. Maybe that
subsystem is complex enough as is.
- It might leak implementation details of a type T to code belonging to
another type or global function, residing within the same file as an
extension to T.
- Maybe there might be more elegant ways to improve or extend the access
control subsystem.

Any thoughts?

Best,
Austin
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution