Conform to Protocol and Keep Property Private Conform to Protocol and Keep Property Private swift swift

Conform to Protocol and Keep Property Private


As @TheAppMentor mentioned, there seems to be no exact solution to this problem as of Swift 4.

There are, however, two approximate solutions:

1.)

Since a protocol in Swift has the access level of internal by default, make the variable also internal. In order for internal to be enforced by the compiler, move the protocol, the class and all of their consumers (users) to a separate module (framework).

/* internal */ protocol ProtocolX: class {    var x: Any { get set }    func performAnyActionOnX()}extension ProtocolX {    func performAnyActionOnX() {}}/* internal */ class A: ProtocolX {    internal var x: Any = 0}

2.)

Give the protocol the access level of private and the variable the access level of fileprivate. In order for the private protocol to be accessible, move the protocol, the class and all of their consumers to the same source file.

private protocol ProtocolX: class {    var x: Any { get set }    func performAnyActionOnX()}extension ProtocolX {    func performAnyActionOnX() {}}class A: ProtocolX {    fileprivate var x: Any = 0}


Since protocol's properties always have the same access level as your protocol has you can create a separate class where you can apply fileprivate level to them e.g.:

public class Props {    fileprivate var x: Int = 0}public protocol ProtocolX: class {    var privateProps: Props { get }}extension ProtocolX {    public func performAnyActionOnX() {        privateProps.x = 5        print(privateProps.x)    }}public class A: ProtocolX {    public let privateProps = Props()        public init() {        privateProps.x = 7    }}

As you can see x has fileprivate access level so it can be accessible in ProtocolX extention and A class implementation only so it behaves as private and you can't change privateProps variable of class A and access to x outside:

let a = A()a.performAnyActionOnX()// Prints: 5let x = a.privateProps.x// error: 'x' is inaccessible due to 'fileprivate' protection level


There is no the exact solution for your question, by the reason stated in the @TheAppMentor's comment. But there some workarounds which may be helpful if you purpose is to make your code understandable for humans (not to trick the compiler).

Compiles in Swift 4.0.

Solution 1: Python-like __privacy

Fast and simple. This solution relies on the user who would agree that properties and functions starting from _ are private and shouldn't be accessed.

protocol ProtocolX: class {    // Public x    var x: Int { get }    // It's private!    var _x: Int { get set }    func performAnyActionOnX()}extension ProtocolX {    var x: Int { return _x }    func performAnyActionOnX(){        _x = 5        print(x)    }}class A: ProtocolX {    var _x: Int = 7}

Solution 2: Additional layer of abstration

Architecturally correct. You should split your protocol on the two parts: private and public.

protocol ProtocolX: class {    var x: Int { get }    func performAnyActionOnX()}protocol ProtocolXImplementation: class {    var _x: Int { get set }}extension ProtocolXImplementation {        var x: Int { return _x }    func performAnyActionOnX(){        _x = 5        print(x)    }}class A: ProtocolX, ProtocolXImplementation {    var _x: Int = 7}// ... somewhere later ...// Hide the implementation when use `A`:let item: ProtocolX = A()