我正在尝试创建一个简单的协议,说明对象是处于“开启”状态还是“关闭”状态。对它的解释取决于实现对象。对于 a UISwitch
,它是开关是打开还是关闭(duh)。对于 a UIButton
,可能是按钮是否处于selected
状态。对于 a Car
,它可能是汽车的引擎是否开启,或者即使它是否在移动。所以我开始创建这个简单的协议:
protocol OnOffRepresentable {
func isInOnState() -> Bool
func isInOffState() -> Bool
}
现在我可以像这样扩展上述 UI 控件:
extension UISwitch: OnOffRepresentable {
func isInOnState() -> Bool { return on }
func isInOffState() -> Bool { return !on }
}
extension UIButton: OnOffRepresentable {
func isInOnState() -> Bool { return selected }
func isInOffState() -> Bool { return !selected }
}
现在我可以制作这些类型的对象数组并循环检查它们是打开还是关闭:
let booleanControls: [OnOffRepresentable] = [UISwitch(), UIButton()]
booleanControls.forEach { print($0.isInOnState()) }
伟大的!现在我想制作一个将这些控件映射到 a 的字典,UILabel
以便在控件更改状态时更改与控件关联的标签的文本。所以我去声明我的字典:
var toggleToLabelMapper: [OnOffRepresentable : UILabel] = [:]
// error: type 'OnOffRepresentable' does not conform to protocol 'Hashable'
哦!正确的!傻我。好吧,那我就用协议组合来更新协议吧(毕竟我这里要使用的控件都是Hashable:UISwitch、UIButton等):
protocol OnOffRepresentable: Hashable {
func isInOnState() -> Bool
func isInOffState() -> Bool
}
但是现在我得到了一组新的错误:
error: protocol 'OnOffRepresentable' can only be used as a generic constraint because it has Self or associated type requirements
error: using 'OnOffRepresentable' as a concrete type conforming to protocol 'Hashable' is not supported
好的...所以我做了一些堆栈溢出挖掘和搜索。我发现许多看起来很有希望的文章,例如Swift 中的 Set 和协议,不支持将某些协议用作符合另一个协议的具体类型,并且我发现那里有一些很棒的文章type erasure
似乎正是我需要的: http://krakendev.io/blog/generic-protocols-and-their-shortcomings , http://robnapier.net/erasure和https://realm.io/news/type-erased-wrappers-in-迅速/仅举几例。
这是我卡住的地方。我已经尝试通读所有这些内容,并且尝试创建一个将Hashable
符合并且也符合我的OnOffRepresentable
协议的类,但我不知道如何将它们全部连接起来。