【问题标题】:Swift: Abstract base class/protocol with private membersSwift:具有私有成员的抽象基类/协议
【发布时间】:2017-10-08 19:21:04
【问题描述】:

根据this answer,我使用协议扩展在 Swift 中创建了一个抽象的类基类结构。这是一个简化的例子:

protocol AbstractBase {
    var _constant: Int { get }
    func _operation(_ val: Int) -> Int
}

public class ConcreteSub: AbstractBase {
    let _constant: Int = 42
    func _operation(_ val: Int) -> Int {
        return val + 2
    }
}

extension AbstractBase {
    func mainOperation(_ val: Int) -> Int {
        return _operation(val + _constant)
    }
}

所以基本上ConcreteSub提供了AbstractBase所需的实现细节,即_constant_operation

我想对客户隐藏这些细节,只公开mainOperation。但是,Swift 不允许我在协议上将成员文件设为私有——如果我执行以下操作

protocol AbstractBase {
    fileprivate var _constant: Int { get }
    // etc

我收到“错误:'fileprivate' 修饰符不能在协议中使用”。

我也不能在子类上应用修饰符——当我尝试时

public class ConcreteSub: AbstractBase {
    fileprivate let _constant: Int = 42
    // etc

我收到“错误:属性 '_constant' 必须声明为内部的,因为它符合内部协议 'AbstractBase' 中的要求”。

最后,当我将整个协议文件设为私有时,我没有收到任何编译错误,但我一直遇到链接错误,我猜这是因为协议是私有的,但子类是公共的。

还有其他我想念的方法吗?

【问题讨论】:

    标签: swift access-control


    【解决方案1】:

    当我需要一个隐藏了一些属性/函数的抽象基时,我会使用带有一些额外 fatalErrorsasserts 的类来在有人尝试使用 Base 而不是实现时崩溃。

    public class AbstractBase {
        init() {
            assert(type(of: self) != AbstractBase.self, "Abstract class")
        }
    
        fileprivate var _constant: Int {
            fatalError("Abstract class")
        }
        fileprivate func _operation(_ val: Int) -> Int {
            fatalError("Abstract class")
        }
    
        func mainOperation(_ val: Int) -> Int {
            return _operation(val + _constant)
        }
    }
    
    public class ConcreteSub: AbstractBase {
    
        fileprivate override var _constant: Int {
            return 42
        }
        fileprivate override func _operation(_ val: Int) -> Int {
            return val + 2
        }
    }
    

    【讨论】:

    【解决方案2】:

    我实际上只是遇到了这个问题。从 Swift 5.1 开始,您可以改为:

    protocol MyProtocol {
        var someVisibleVar: String { get }
        func someVisibleFunc()
    }
    
    fileprivate extension MyProtocol {
        var someFilePrivateVar: String {
            "whatever"
        }
    
        func someFilePrivateFunc() {
            print("someFilePrivateFunc() was called with \(someVisibleVar)")
        }
    }
    
    class SomeClass: MyProtocol {
        var someVisibleVar: String { "whatever" }
    
        func someVisibleFunc() {
            if someFilePrivateVar == someVisibleVar {
                someFilePrivateFunc()
            }
        }
    }
    
    class SomeOtherClass: MyProtocol {
        var someVisibleVar: String { "something else" }
    
        func someVisibleFunc() {
            if someFilePrivateVar == someVisibleVar {
                someFilePrivateFunc()
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-28
      • 2011-01-08
      • 2016-05-08
      • 1970-01-01
      • 2023-02-09
      相关资源
      最近更新 更多