[swift-evolution] access control

Thorsten Seitz tseitz42 at icloud.com
Sun Jan 24 02:44:48 CST 2016


	
> 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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160124/c652eeef/attachment.html>


More information about the swift-evolution mailing list