Swift:具有私有成员的抽象基类/协议



根据这个答案,我在 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 不允许我在协议上使成员 fileprivate -- 如果我执行以下操作

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

我收到"错误:'文件私有'修饰符不能在协议中使用"。

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

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

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

最后,当我制作整个协议 fileprivate 时,我没有收到编译错误,但我总是遇到链接错误,我想这是因为协议是私有的,但子类是公共的。

我错过了另一种方式吗?

当我需要一个隐藏了一些属性/函数的抽象基础时,我会使用带有一些附加fatalErrors的类,并且每当有人尝试使用 Base 而不是实现时,asserts崩溃。

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
}
}

我实际上刚刚遇到了这个问题。从 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()
}
}
}

最新更新