In my application I want to create an generic method which creates an array of object depening on the given type T.
I created the following function:
func getArray<T : ROJSONObject>(key:String) -> T[] {
var elements = T[]()
for jsonValue in getValue(key).array! {
var element = T()
element.jsonData = jsonValue
elements.append(element)
}
return elements
}
Now I want to pass the type when I call the method, so it does know which type it should create internally. I think in Java and C# you can use a method like that:
object.getArray<Document>("key")
When I call it like that, I always get the error:
Cannot explicitly specialize a generic function
So my fix was to define an additional parameter containing an instance of the type T so it does automatically detect the type:
func getArray<T : ROJSONObject>(key:String, type:T) -> T[] {
var elements = T[]()
for jsonValue in getValue(key).array! {
var element = T()
element.jsonData = jsonValue
elements.append(element)
}
return elements
}
Is there really no other way to get that behaviour without passing an unused instance? Or am I misunterstanding something?
Further Testing
After the answer of jtbandes I did some more testing. I tried to force the Type by adding the as
in the call.
class Person {
init() { }
func getWorkingHours() -> Float {
return 40.0
}
}
class Boss : Person {
override func getWorkingHours() -> Float {
println(100.0)
return 100.0
}
}
class Worker : Person {
override func getWorkingHours() -> Float {
println(42.0)
return 42.0
}
}
func getWorkingHours<T : Person>() -> T {
var person = T()
person.getWorkingHours()
return person
}
var worker:Worker = getWorkingHours() as Worker
var boss:Boss = getWorkingHours() as Boss
worker.getWorkingHours() // prints out 40.0 instead of 42.0
boss.getWorkingHours() // prints out 40.0 instead of 100.0
So somehow the type is always the base type even I've specified the type with the as
keyword. I know the example does not make much sense, but it was just for testing purpose..
I worked around this by borrowing from the swift runtime function unsafeBitCast
.
It's declared as func unsafeBitCast<T, U>(x: T, _: U.Type) -> U
and you can call it as unsafeBitCast(value, MyType)
.
Applied to your function this would be
func getArray<T : ROJSONObject>(key:String, _: T.Type) -> T[] {
// function stays the same
}
And you can call it like this
getArray("key", Document)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With