我想做这样的事情:
func match(firstAny: Any, _ secondAny: Any) -> Bool {
switch (firstAny, secondAny) {
case (let first as Equatable, second as Equatable):
return first == second
case (let first as AnyObject, second as AnyObject):
return first === second
default:
return false
}
}
但我不能使用Equatable
类型的情况。如何解决它?
答案 0 :(得分:3)
成为Equatable
并不意味着您可以将==
应用于其他所有Equatable
,因此这不起作用。 Equatable
类型只能等同于它们自己的类型。因此,即使Swift可以做到这一点,你的方法也是错误的。您需要确保这两种类型具有相同的Self
(在存在子类时有些复杂)。
有一些方法可以获得类似的重载,但我发现它们非常脆弱。例如:
func match<Eq: Equatable>(first: Eq, _ second: Eq) -> Bool {
return first == second
}
func match(first: AnyObject, _ second: AnyObject) -> Bool {
return first === second
}
func match(first: Any, _ second: Any) -> Bool {
return false
}
这可以在非常有限的情况下工作,但是如果编译器无法在编译时证明类型是Equatable
(并且在很多情况下理论上它可以证明它,但事实上它确实如此不),然后你会调用错误的函数。调试它真的很痛苦。
几乎所有情况下的答案都是重新设计你的系统而不需要这个,通常是通过处理你的程序实际需要的类型,而不是试图为每种可能的类型解决它。使事物过于通用是Swift中的常见问题;你击中了Swift无法实际处理的所有尖锐边缘。我从未见过这些解决方案可靠地工作。
(值得注意的是,如果match
可以简单地实现而且没有奇怪的角落案例,那么stdlib几乎肯定会以这种方式实现==
。事实==
没有以这种方式工作是一个强烈的建议,它是一个比Swift中出现的问题复杂得多的问题。偶尔stdlib是错误的,但通常情况就是这样,如果你发现自己添加了“明显”缺失的部分,它可能会有惊喜。我已经多次烧过自己......)