[swift-evolution] Protected Access

Jonathan Hull jhull at gbis.com
Fri Oct 7 17:00:13 CDT 2016


The discussion of private/fileprivate reminded me of other access modifier issues that have been bugging me.  I agree that the old system is better, but I am ambivalent about changing it back…

What I pretty much constantly want is an access modifier which lets me access something from an extension (which is potentially in a different file), but otherwise have it be private.  The vast majority of my use of “fileprivate” is so that I can access internal properties/functions from an extension (which I am forced to place in the same file).

Access from subclasses is a larger discussion, but I run into this most often with Structs and their extensions.


The other pieces which seem to be missing are modifiers which allow finer grained control of how class methods are overridden and used.  

It is a fairly common pattern in cocoa, for example, to have customization point methods which are designed to be overridden, but are not supposed to be called directly. Right now, this is enforced via documentation.  One potential solution is to have a @noExternalCall attribute which says that it can only be called from the class/subclass/extensions… but if you think about it, this is basically another view of the first issue. If we could mark that method as only visible within the class/subclasses/extensions, then the behavior we want just falls out naturally. It can’t be called externally, because no one on the outside can see it.

I also occasionally run into this with protocols.  I find that I have a property on the protocol which is needed for default implementations, but I really want to make it private with respect to the protocol (and its inheritors/extensions).  That is, I want the implementor of the protocol to have visibility for that property, but not the caller of the protocol.  Right now, I have to expose it to everyone (which clutters my external API), and then note in documentation not to call those properties.

Basically, I want to do the following:

	protocol P {
		hidden var a:Int
		var b:Int
	}

	extension P {
		var c:Int { return self.a + self.b}
	}

	struct A:P {
		private var a:Int = 5  // ‘A’ must implement, but it doesn’t have to expose it externally
		var b:Int = 2
	}

	struct B:P{
		var a:Int = 3  // ‘B’ chooses to expose, which is ok too
		var b:Int = 4
	}

	let ans = A().c  // 7
	let ohNo = A().a // Error!

Basically ‘hidden’ in the protocol means that the implementor must implement the property, but it is not required to expose it to the world.  I don’t really care whether that is spelled hidden, protected, or private, but I would use this fairly often.

Thanks,
Jon




More information about the swift-evolution mailing list