有没有办法检查泛型类型是否符合Equatable?我希望能够检查相同泛型类型的两个对象是否相等,或者相等对它们没有意义。
由于Equatable只能用作通用约束(因为它有Self或associatedType要求),我尝试过使用泛型重载:
//If T is equatable, this is more specific so should be called
func equals<T:Equatable>(lhs:T, rhs:T) -> Bool?{
return lhs == rhs
}
//This should only be called if T is not equatable at compile time
func equals<T>(lhs:T, rhs:T) -> Bool?{
return nil
}
这在使用特定类型调用时有效,例如: equals(lhs:1, rhs:1)
按预期返回true
。但是,如果在通用上下文中调用它,它总是返回nil
:
func doSomethingThenCheckEquals<T>(lhs:T, rhs:T){
//Do something here which has no type requirements
//Check if the two objects are equal - would usually do something with the result
//This will always use equals<T> and never equals<T:Equatable>, so will always be nil
_ = equals(lhs:lhs, rhs:rhs)
}
有没有办法达到预期的效果?
此外,根据this answer,编译器以带有动态类型检查的单个实现开始,但在某些情况下可以创建专门的实现。在编译器创建专用实现的情况下,它的行为是否与第一种情况类似(equals(lhs:1, rhs:1)
返回true
)?
答案 0 :(得分:0)
编译器按预期执行其工作。您声明的第二个方法与第一个方法无关,因此它对T
一无所知。
Generic是前向声明,这意味着我们需要告诉编译器它将遵循什么协议,然后编译器将采取所有必要的步骤来适应它。也许将来,我们可以期待函数调用级别类型解释但是目前,它不可用。
func doSomethingThenCheckEquals<T>(lhs:T, rhs:T){
//Do something here which has no type requirements
//Check if the two objects are equal - would usually do something with the result
//This will always use equals<T> and never equals<T:Equatable>, so will always be nil
_ = equals(lhs:lhs, rhs:rhs)
}
最好的解决方案是使用where
子句。
func doSomethingThenCheckEqual<T>(lhs: T, rhs: T) where T:Equatable {
}
详细了解here。