I have generic and I want to be able to initialize it with specific constrains. The constraints are only there for initialization. The rest of the class doesn't care. Here is a simplified example:
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)
}
}
You can see there's two initializers. The second one obviously works fine. However, in the first one the local type T
is mismatched with the struct's generic Type. So, for example, attempting to insert data I get Cannot invoke 'insert' with an argument list of type '([T])'
. Is it possible for me to specialize the Struct's generic type only for the initialization or a specific function?
Note, I've already tried init<T where T:Equatable>(data: [T])
to the same effect.
Update
I'm using the following workaround: I create a top level function and removing the specialized init:
func equatableHandler<T: Equatable>(left: T, right: T) -> Bool {
return left == right
}
Clients of the struct can initialize using: Generic(compareHandler: equatableHandler, data: data)
It's not quite the "convenience" of using a specialized init
, but I suppose it works well enough for my purposes. I'm not a fan of creating top-level functions, but the generic is used so often for "Equatable" generics that it makes sense for me to define the handler once for clients to use.
The problem is that the first init method
init<T: Equatable>(data: [T])
introduces a local type placeholder T
which hides (and is completely
unrelated to) the placeholder T
of the Generic
type, so it
is essentially the same problem as in Array extension to remove object by value.
As of Swift 2 you can solve that with a "restricted extension":
extension Generic where T : Equatable {
init(data: [T]) {
let handler: (T, T) -> Bool = { $0 == $1 }
compare = handler
// ...
}
}
For Swift 1.x the only solution is probably to define a global helper function
func makeGeneric<T : Equatable>(data: [T]) -> Generic<T> {
return Generic(compareHandler: { $0 == $1 }, data: data)
}
(and I could not think of a sensible name for the function :).
来源:https://stackoverflow.com/questions/31703790/swift-generic-constraints-in-init