符合协议并保持私有财产

Sam*_*Dos 6 architecture protocols private swift

我需要在一致的类中使用协议属性作为私有.但是编译器拒绝这样做.我该如何实现呢?

protocol ProtocolX: class {
    var x: Int { get set }

    func performAnyActionOnX()
}

extension ProtocolX {
    func performAnyActionOnX() {
        x = 5
        print(x)
    }
}

class A: ProtocolX {
    private var x:Int = 7
}
Run Code Online (Sandbox Code Playgroud)

谢谢.

Gar*_*ary 6

正如 @TheAppMentor 提到的,从 Swift 4 开始,这个问题似乎还没有确切的解决方案。

然而,有两个近似解:

1.)

internal由于 Swift 中的协议默认具有访问级别,因此将变量也设置为internal。为了internal由编译器强制执行,请将协议、类及其所有消费者(用户)移动到单独的模块(框架)中。

/* internal */ protocol ProtocolX: class {
    var x: Any { get set }

    func performAnyActionOnX()
}

extension ProtocolX {
    func performAnyActionOnX() {}
}

/* internal */ class A: ProtocolX {
    internal var x: Any = 0
}
Run Code Online (Sandbox Code Playgroud)

2.)

为协议指定访问级别private,为变量指定访问级别fileprivate。为了使private协议可访问,请将协议、类及其所有使用者移动到同一个源文件中。

private protocol ProtocolX: class {
    var x: Any { get set }

    func performAnyActionOnX()
}

extension ProtocolX {
    func performAnyActionOnX() {}
}

class A: ProtocolX {
    fileprivate var x: Any = 0
}
Run Code Online (Sandbox Code Playgroud)


kel*_*lin -2

根据 @TheAppMentor 评论中所述的原因,您的问题没有确切的解决方案。但是,如果您的目的是使代码易于人类理解(而不是欺骗编译器),那么一些解决方法可能会有所帮助。

在 Swift 4.0 中编译。

方案一:类似Python的__privacy

快速而简单。此解决方案依赖于用户同意从 开始的属性和函数_是私有的并且不应被访问。

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
}
Run Code Online (Sandbox Code Playgroud)

解决方案 2:附加抽象层

从架构上来说是正确的。您应该将协议分为两部分:私有和公共。

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()
Run Code Online (Sandbox Code Playgroud)