[swift-evolution] access control
Ilya Belenkiy
ilya.belenkiy at gmail.com
Mon Jan 25 07:45:26 CST 2016
Formal means enforceable by the compiler. File based access control is
useful as well but not as a substitute for real data encapsulation.
On Mon, Jan 25, 2016 at 8:13 AM Taras Zakharko <
taras.zakharko at googlemail.com> wrote:
> I disagree with Ilya on his stance on ‘private’. I do understand the
> argumentation, but the reasoning seems overly formal to me and the
> classical solution (private visible only within the class) also comes with
> a number of drawbacks that result in things like friends declarations in
> C++. It is nice to have relationships between entities explicit, but one
> can go overboard with the rigidity.
>
> However, I also strongly agree with Thorsten that a subclass (but not
> public) visible modifier has a lot of uses. I would prefer to have four
> levels of access:
>
> private (file scope)
> internal (module scope)
> protected (subclass scope)
> public
>
> Best,
>
> Taras
>
>
> On 24 Jan 2016, at 09:44, Thorsten Seitz via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Am 23.01.2016 um 16:56 schrieb Ilya Belenkiy via swift-evolution <
> swift-evolution at swift.org>:
>
> I hope that access control can be revisited. It is the number one
> complaint about Swift that I hear from experienced developers. The current
> solution came as a complete surprise to every ObjC developer I've talked
> to. The natural expectation was that a strong access control system would
> be part of a strong type system. I already submitted a pull request with a
> proposal for this after a lengthy discussion here, but so far it was
> ignored. I hope that this can be revisited. Even if most people who
> responded earlier in this list decided that they were happy with the
> current state, it represents a tiny fraction of people using the language,
> and at least all the people I talked to strongly disagree but just aren’t
> on the list.
>
> Right now access control is file based and not API based. This is much
> easier to implement but useless to express that certain elements of a class
> are implementation details that are not meant to be used anywhere else
> (someone can add more code to the same file and get access to the
> implementation details without modifying the class).
>
>
> I think the file based approach for `private` has advantages because it
> allows putting several things that have to know each other deeply into the
> same file (C++ would use friend access for that).
>
>
> It’s also impossible to hide APIs that are meant only for customization
> points of subclasses.
>
>
> Here I agree. What I am really missing is the ability to declare something
> „protected“ in a protocol (or class) which is not part of the public API
> but which I then can use in its default implementation but which has to be
> provided by implementors of the protocol.
>
> Example (shortened and simplified to just show the relevant parts):
>
> public protocol StandardGraphTraversal {
> // push() and pop() are implementation details and not part of the API
> protected func push(vertex: Vertex)
> protected func pop() -> Vertex?
>
> public func next() -> Vertex?
> }
>
> public extension StandardGraphTraversal {
>
> // leaving out things like visitor callbacks and coloring the visited
> vertices
> public func next() -> Vertex? {
> guard let source = pop() else { // using pop() here
> return nil
> }
> for target in graph.neighborsOf(source) {
> if shouldFollowVertex(target) {
> push(vertex) // using push() here
> }
> }
> }
> }
>
> // supplying the implementation detail: using a queue results in breadth
> first traversal
> public struct BreadthFirstTraversal : StandardGraphTraversal {
> var queue: Queue<Vertex> = Queue()
>
> protected func push(vertex: Vertex) { return queue.push(vertex) }
> protected func pop() -> Vertex? { return queue.pop() }
> }
>
> // supplying the implementation detail: using a stack results in depth
> first traversal
> public struct DepthFirstTraversal : StandardGraphTraversal {
> var stack: Stack<Vertex> = Stack()
>
> protected func push(vertex: Vertex) { return stack.push(vertex) }
> protected func pop() -> Vertex? { return stack.pop() }
> }
>
> Currently I cannot express that in Swift and have to make push() and pop()
> public :-(
>
> (Allowing `internal` in public protocols would be sufficient in my example
> but would not help in more general cases where the implementors would have
> to be provided in another module by the framework user).
>
>
> .NET has a good solution that respects the OOP terminology and deals with
> accessibility in modules and at the API level:
> https://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx
>
>
> `public` and `internal` seem to be quite the same as in Swift.
> `private` is based on the type instead of the file. I think Swift’s file
> based `private` is better because it allows to express the same by putting
> a type into its file alone and allows to create strongly interdependent
> types by putting them together into the same file.
> `protected` is what I’m missing as well
> `protected internal` seems to be the union of `protected` and `internal`.
> I think that is not needed and is probably there to allow testing for which
> Swift has a nicer solution with @testable imports.
>
> In short the only thing which is missing IMO is `protected`.
>
> -Thorsten
>
> _______________________________________________
> 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/20160125/e8c8f42d/attachment.html>
More information about the swift-evolution
mailing list