[swift-evolution] Type access level as the default for its members?

Eric-Paul Lecluse epl at lecluse.org
Fri Jul 22 05:34:10 CDT 2016

To illustrate my question below, here are three publicly modified entities:
a struct, an enum and an extension, whose properties lack explicit access

    public struct Car {
        var wheel: [Wheel]
        var licensePlate: String

        func combust() { ... }

    public enum Wheel {
        case big
        case small

        var revolutionDistance: Double { ... }

    public extension Car {
        func park() { ... }

The default access level for every member is `internal` for all members of
an original type. Therefore both `combust()` and `revolutionDistance` are
publicly inaccessible. For extensions, this is different, `park()` _is_
publicly accessible (as would be computed properties if it had any) because
the extension is marked `public`. There's no option to modify an enum's
cases individually (nor should there be), they're inherently linked to the
enum's access level.

When modifying any of the entities to `private`, their members become
inaccessible by association. If a type isn't accessible, neither are its
members. Thus for the `private` case, the behavior feels more like what the
extension modifier did in the first place.

Not immediately apparent from this example is that the struct has an
implicit constructor (lacking any explicit ones), whose access level also
defaults to `internal`. This means the Car-struct can't be constructed
outside of its defining module, until we create an explicit initializer
with the `public` access modifier.

# Problems
The current approach is very verbose for any kind of access modification.
Public structs that are intended to expose their members, require
explicitly marked `public` modifiers everywhere. Consider the case where
you want to expose a previously hidden (internal or private) type, you need
to modify every individual member. Except if you're modifying an extension,
in that case you only need to modify in one place. This means that
conceptually, putting a `public` or `private` modifier on a type behaves
differently from putting one one an extension, with regard to a type's
members, which can lead to confusion (and has in my case, and with several
fellow developers).

# Idea
What if the default access level were chosen differently? Instead of being
`internal` by default, or `private` by association, what if the
_type-level_ access modifier would determine the default for _all_ members,
unless explicitly modified, including `public` and to-be-introduced ones?

This would...
1. equalize the conceptual behavior between access levels of an original
type and the ones of their extensions.
2. greatly reduce verbosity on members due to explicit access level
3. make it easier to modify the access level of an entire type, without
requiring modification of individual members.
4. reduce the requirement of public constructors where they would match the
implicit ones.
5. still allow exceptions on an individual level

What do you think?

* I'm using the word 'entity' to lump types and extensions together under
one term. There must be a better term, please do share!
* My examples are based off of my experience with Swift 2.2, even though I
believe the concepts still apply in 2.3 and the 3.0-beta.
* Protocols don't allow access modification on individual members, of
course, similar to an enum's cases.
* Didn't find any similar topics in the [commonly rejected list](
* There's a [newly accepted proposal](
that adds `fileprivate` as a fourth access level modifier.

Other discussions about access levels, yet not what I was looking for:
* [Default access control / Access control blocks] (
* [Access modifier blocks] (
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160722/60326a86/attachment.html>

More information about the swift-evolution mailing list