我有两个协议,定义了我项目中有趣部分的基本结构(示例代码是无意义的,但描述了问题):
1) 一个委托协议,类似于UITableViewController的dataSource协议,可以访问某些信息:
protocol ValueProvider {
var value: Int { get }
}
2) 一个实体的接口协议,用于处理来自上面的信息(这就是所谓的“协议优先”方法的构想):
protocol DataProcessor {
var provider: ValueProvider { get }
func process() -> Int
}
关于数据处理器的实际实现,现在我可以选择枚举、结构体和类。有几个不同抽象级别的信息处理方式,因此类似乎是最合适的(但我不想将其作为最终决定,因为它可能会在未来的使用情况中改变)。我可以定义一个基础处理器类,在其上面可以构建几个特定情况的处理器(这在结构体和枚举中是不可能的):
class BaseDataProcessor: DataProcessor {
let provider: ValueProvider
init(provider: ValueProvider) {
self.provider = provider
}
func process() -> Int {
return provider.value + 100
}
}
class SpecificDataProcessor: BaseDataProcessor {
override func process() -> Int {
return super.process() + 200
}
}
到目前为止一切都很顺利。然而,在实际情况中,特定的数据处理器与处理的值紧密绑定(与基础处理器相反,对于基础处理器,这种情况并不是真的),因此我希望将ValueProvider直接集成到子类中(作为比较,通常UITableViewControllers是它们自己的dataSource和delegate)。
起初我考虑添加一个协议扩展来进行默认实现:
extension DataProcessor where Self: ValueProvider {
var provider: ValueProvider { return self }
}
如果我没有不想让值与类绑定的BaseDataProcessor类,那么这可能是有效的。然而,从BaseDataProcessor继承且采用ValueProvider的子类似乎在内部覆盖了该实现,因此这不是一个选项。我继续尝试并得到了如下结果:
class BaseDataProcessor: DataProcessor {
// Yes, that's ugly, but I need this 'var' construct so I can override it later
private var _provider: ValueProvider!
var provider: ValueProvider { return _provider }
func process() -> Int {
return provider.value + 10
}
}
class SpecificDataProcessor: BaseDataProcessor, ValueProvider {
let value = 1234
override var provider: ValueProvider { return self }
override func process() -> Int {
return super.process() + 100
}
}
这段代码可以编译并且乍一看似乎符合我的需求。但是,它并不能解决问题,因为它会产生一个引用循环,可以在Swift playground中看到:
weak var p: SpecificDataProcessor!
autoreleasepool {
p = SpecificDataProcessor()
p.process()
}
p // <-- not nil, hence reference cycle!
另一个选项可能是向协议定义中添加类约束。但是,据我所知,这将破坏POP方法。
总之,我的问题可以归结为以下内容:如何在不限制协议设计过程中使面向协议编程和委托模式共同工作?