当创建一个没有约束的普通泛型函数时,它按预期工作,即:
func select<T,U>(x:T, f:(T) -> U) -> U {
return f(x)
}
类型流入closure参数,它允许我以强类型访问它,即:
var b1:Bool = select("ABC") { $0.hasPrefix("A") }
var b2:Bool = select(10) { $0 > 0 }
当我添加Equatable
约束时,它继续有效:
func selectEquatable<T : Equatable, U : Equatable>(x:T, f:(T) -> U) -> U {
return f(x)
}
var b3:Bool = selectEquatable("ABC") { $0.hasPrefix("A") }
但由于某种原因,在使用Comparable
约束时失败:
func selectComparable<T : Comparable, U : Comparable>(x:T, f:(T) -> U) -> U {
return f(x)
}
var b4:Bool = selectComparable("ABC") { $0.hasPrefix("A") }
因构建错误而失败:
找不到会员'hasPrefix'
但它确实允许在类型流经String
var b5:String = selectComparable("ABC") { $0 }
查看API文档显示String为Comparable
:
extension String : Comparable {
}
它甚至允许从String隐式转换为Comparable
:
var str:Comparable = ""
那么为什么我不能将它作为一个强类型字符串在我的Closure中访问?
var b4:Bool = selectComparable("ABC") { $0.hasPrefix("A") } //build error
答案 0 :(得分:1)
这不是String
。您的约束{ $0.hasPrefix("A") }
的返回类型为Bool
,已分配给U
。 Bool
为Equatable
,但不是Comparable
。
您可能希望闭包返回Bool
,但selectComparable
返回U
。
以下证据表明,返回String
(Comparable
)而不是Bool
(不是Comparable
)将会编译:
func selectComparable<T: Comparable, U: Comparable>(x:T, f:(T) -> U) -> U {
return f(x)
}
var b4 = selectComparable("ABC") { (str: String) -> String in str }
答案 1 :(得分:1)
您的selectComparable声明不正确。
func selectComparable<T: Comparable, U: Comparable>(x:T, f:(T) -> U) -> U {
return f(x)
}
U:Comparable不适用于Bool类型,它不是Comparable,只有Equatable
这样可以正常使用
func selectComparable<T: Comparable, U>(x:T, f:(T) -> U) -> U {
return f(x)
}
将
func select<T:Comparable,U: Equatable>(x:T, f:(T) -> U) -> U {
return f(x)
}