[swift-evolution] [swift-evolution-announce] [Review] SE-0159: Fix Private Access Levels

Brent Royal-Gordon brent at architechies.com
Tue Mar 21 03:54:43 CDT 2017


> On Mar 20, 2017, at 8:26 PM, Charles Srstka via swift-evolution <swift-evolution at swift.org> wrote:
> 
> the concern with extensions could be easily solved simply by giving extensions access to private members of the extended type as long as those extensions are in the same module/submodule (or file, if you prefer, but I don’t). This would probably eliminate almost all of the use cases for fileprivate, as well as freeing us from the sometimes clumsy situation where we’re rather artificially forced to use files as a scope, instead enabling us to organize code into files as is appropriate for the project.


I think that many advocates of scoped private misunderstand critics' concerns about extensions.

One of the nice things about file-based `private` is that it allows access from extensions not only on the same type, but also on *other* types. For example, suppose I have a Book type and I want to allow them to be added to bookshelves:

	class Bookshelf {
		// I'm using file-based private here
		private(set) var books: [Book]
		
		func addBook(_ book: Book) {
			book.bookshelf = self
			books.append(book)
		}
	}

I also want to have a removal method, but—much like `UIView` and `NSView`'s `removeFromSuperivew`—I want that method to be on `Book`, not `Bookshelf`. With file-based private, that's no problem—just drop the code in an extension in the same file:

	extension Book {
		func removeFromBookshelf() {
			guard let shelf = bookshelf else { return }
			shelf.remove(at: shelf.books.index(of: self)!)
			bookshelf = nil
		}
	}

When we talk about file-based private being "better for extensions", we're *not*—or at least not necessarily—talking about it being better for the pattern of splitting a type into several different extensions to group related code together. We're talking about the pattern of splitting a *concern* across several different *types* by extending all of them, taking advantage of Swift's flexible scoping to encapsulate details even when the type hierarchy doesn't match the encapsulation boundaries you want.

So allowing `private` members to be seen by extensions anywhere in a project doesn't address this issue; in fact, it actively and aggressively undermines it, making it impossible to encapsulate any implementation details at a scope smaller than a single type. For myself and others like me, it is the exact opposite of what we want.

-- 
Brent Royal-Gordon
Architechies

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


More information about the swift-evolution mailing list