Aar*_*man 6 generics init swift
我有泛型,我希望能够使用特定的约束来初始化它.约束仅用于初始化.班上的其他人都不在乎.这是一个简化的例子:
struct Generic<T> {
let compare: (T, T) -> Bool
init<T: Equatable>(data: [T]) {
let handler: (T, T) -> Bool = { $0 == $1 }
compare = handler
insert(data)
}
init(compareHandler: (T, T) -> Bool, data[T]) {
compare = self.compareHandler
insert(data)
}
}
Run Code Online (Sandbox Code Playgroud)
你可以看到有两个初始化器.第二个显然工作正常.但是,在第一个中,本地类型T与struct的泛型类型不匹配.因此,例如,尝试插入我得到的数据Cannot invoke 'insert' with an argument list of type '([T])'.我是否可以仅针对初始化或特定函数专门化Struct的泛型类型?
请注意,我已经尝试init<T where T:Equatable>(data: [T])过同样的效果.
我正在使用以下解决方法:我创建一个顶级函数并删除专用的init:
func equatableHandler<T: Equatable>(left: T, right: T) -> Bool {
return left == right
}
Run Code Online (Sandbox Code Playgroud)
struct的客户端可以使用以下命令初始化: Generic(compareHandler: equatableHandler, data: data)
它不是使用专业的"便利" init,但我认为它对我的目的来说足够好.我不是创建顶级函数的粉丝,但泛型经常用于"Equatable"泛型,因此我为客户端定义一次处理程序是有意义的.
问题是第一个init方法
init<T: Equatable>(data: [T])
Run Code Online (Sandbox Code Playgroud)
引入了一个本地类型的占位符T,它隐藏(并且与T该Generic类型的占位符完全无关),因此它与Array扩展中的基本相同的问题是按值删除对象.
从Swift 2开始,你可以通过"限制扩展"来解决这个问题:
extension Generic where T : Equatable {
init(data: [T]) {
let handler: (T, T) -> Bool = { $0 == $1 }
compare = handler
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
对于Swift 1.x,唯一的解决方案可能是定义全局辅助函数
func makeGeneric<T : Equatable>(data: [T]) -> Generic<T> {
return Generic(compareHandler: { $0 == $1 }, data: data)
}
Run Code Online (Sandbox Code Playgroud)
(我无法想到这个功能的合理名称:).