Reputation: 15248
I have protocol P
, class A and B
and my aim is to call generic method a<T: P>(_: T.Type)
with class type parameter created from strings.
protocol P: class {
static var p: String { get }
}
extension P {
static var p: String { return String(describing: self) }
}
class A: P {
func a<T: P>(_: T.Type) {
print(T.p)
}
}
class B: P {}
Below code works because forcefully casting to B.Type fixes the class type
let b = "B"
let type = NSClassFromString(b) as! B.Type
A().a(type)
But if lets say we have an array of class names without knowing their concrete types, how can we pass those?
["ClassA", "ClassB", "ClassC"].forEach({ className in
let type = NSClassFromString(className) as! ????
A().a(type)
})
Upvotes: 3
Views: 557
Reputation: 47896
In Swift, type parameters in generic declarations needs to be solved at compile-time.
So, your ????
needs to be a concrete type conforming to P
. But you cannot use any of the concrete types A.Type
or B.Type
as you describe.
And you may know you cannot use P.Type
, as protocol P
does not conform to P
itself in Swift.
How about declaring the method a(_:)
as non-generic?
class A: P {
func a(_ type: P.Type) {
print(type.p)
}
}
["ModuleName.A", "ModuleName.B"].forEach({ className in
let type = NSClassFromString(className) as! P.Type
A().a(type)
})
You can pass class objects of type P.Type
to the argument of type P.Type
.
Upvotes: 2