通用枚举函数参数?

时间:2019-09-11 03:05:11

标签: swift generics enums

我有很多枚举,例如:

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中,无需任何其他代码即可轻松完成此操作,这就是我感到困惑的原因。

1 个答案:

答案 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)的不变性。由于ab的类型可以不同,因此在大型系统中很容易弄乱。

    • 很少有意义,并且很少有用。考虑您的情况: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)

一样使用它