Protocol methods/properties are supposed to be public/internal/open by their very nature. You can think of a protocol as describing a very specific shape that something should conform to. Having the entirety of the description public is a requirement to having something conform to it.
I looked at your example in the pdf and it looks like your main reasoning is so that you can create a protocol extension to add some default functionality without exposing access to a particular property. I think protocols aren't the right tool for the job here.
Given this statement and your example I feel like inheritance might suit your use case better. Protocols shouldn't be used everywhere for everything you do. In this case I think it's worth looking at all of the tools you have available and picking the right one for the job at hand.
I feel like inheritance might suit your use case better.
In this particular use case, yes. If OP is trying to achieve something like mix-ins with internal state, though, then inheritance doesn't easily support that model.
However, I think a protocol-based composition approach would work. Let the VC conform to the protocol, but the methods simply call into another data structure within the VC that actually holds the state and also conforms to the protocol.
The issue is with private properties inside the Class, they can't be accessed anywhere outside the file, even outside the file extension. This is good feature
A workaround is to have a function accept all the properties which were private inside the Protocol, and have a protocol extension implement the function.
protocol X {
func doSomething(_ label: UILabel) // the label is private property in a class
}
extension X {
func doSomething(_ label) { /* implementation */}
}
class ViewController: X {
private var label = UILabel()
func viewDidLoad() {
doSomething(label)
}
/// use this implementation to do the mixin behavior from outside the class
func exposedFunction() {
doSomething(label)
}
}
This way, a superView or another class can trigger private method update by calling the exposedFunction
let vc = ViewController()
vc.doSomething(vc.label) /// ERROR Cannot access private property `Label`
vc.exposedFunction() /// This Compiles
Your approach should work, but you are exposing the X.doSomething method to the outside world on your VC, and exposedFunction is not codified as the access to X.doSomething. I think the root of your troubles may be that you are trying to hang too much implementation detail on the protocol.
My thought was something more like:
protocol X {
func doSomething()
}
class Mixin {
private var state = ...()
func doSomething(_ label) { /* something with label and state */ }
}
class ViewController : X {
private var label = UILabel()
private var mixin = Mixin()
func doSomething() { mixin.doSomething(label) }
}
In this approach, the Mixin class can contain all of the mixin-related functionality, rather than trying to hang it off the protocol, and the protocol itself can be better suited to the behavior expected by consumers of the VC.
And, if you need the mixin itself to have some common interface (for example, the actual type of the mixin in the VC might vary depending upon application needs) you can add a mixin protocol as well to better decouple the mixin from the VC.
I do feel there are times when using a protocol extension to carry shared functionality (that depends on private properties) rather than a separate data structure would be nice as it avoids us having to inject yet another dependency or creating an object for what may be a very small bit of code.