我有很多枚举,例如:
enum Fruit {
case apple, pear, banana, melon
}
enum Wood {
case oak, birch, mahogany
}
如果两个指定的通用枚举值相同,我想编写一个静态函数进行比较。
funct myCmp<T>(a: T, b: T) -> Bool {
return a == b // cannot compare generic types
}
这怎么办?在Java中,无需任何其他代码即可轻松完成此操作,这就是我感到困惑的原因。
答案 0 :(得分:0)
Java对平等的定义更为广泛。可以比较任何两个对象。这具有明显的好处,但是它具有很多复杂性和缺点。例如:
大多数对象只能与同一个类的对象进行比较,因此最终在equals()
的每个实现中都会重复很多样板,例如:
@Override
public boolean equals(Object o) {
// self check
if (this == o)
return true;
// null check
if (o == null)
return false;
// type check and cast
if (getClass() != o.getClass())
return false;
Person person = (Person) o;
// ACTUAL comparison starts here.
}
引入细微但令人困惑的错误真的很容易,这些错误源于equals
的意外非对称实现。您必须确保Equals
的每个实现都满足a.equals(b) == b.equals(a)
的不变性。由于a
和b
的类型可以不同,因此在大型系统中很容易弄乱。
Fruit.apple
不等于Wood.oak
,但是您对其进行了切片。比较是无稽之谈。 Swift的模型更受限制。如果您查看Equatable
,则说明两个参数的类型均为Self
。上面的Java代码中的三个检查中的两个(参数为非null且其类型匹配)是不必要的,因为从字面上说服类型系统提供nil
或错误键入实际上是不可能的对象作为==
的参数。
后来完全误会了:
您可以编写一个函数,该函数比较(单一)通用类型T
的任何对象,但是您所缺少的是一个常量,T
是可等于的。不知道T
是等价的,您的函数就无法确定是否存在适当的==
。
这是您的示例:
func myCmp<T: Equatable>(a: T, b: T) -> Bool {
return a == b
}
对于您评论中更具体的示例,我将在Sequence
上使用扩展名,而不是使用函数:
extension Collection where Element: Equatable {
func allEqual(to desiredElement: Element) -> Bool {
for element in self {
if element != desiredElement { return false }
}
return true
}
}
并像[fruitA, fruitB, fruitC].allEqual(to: .apple)