Reputation: 27221
I am confused using generics.
I want to implement something like this:
let assume WantedClass as
class WantedClass<T>: NSObject where T: SomeBasicProtocol {
....
}
and an enum
enum Provider: Int {
case one = 1
case two
case three
var providerClass: SomeBasicProtocol.Type {
switch self {
case .one:
return SomeClass1.self
case .two:
return SomeClass2.self
case .three:
return SomeClass3.self
}
}
}
when I try to define an instance
let provider: Provider = .one
let GenericClassIWantToInject = provider.providerClass
let wantedInstance = WantedClass<GenericClassIWantToInject>()
it yields this error:
Use of undeclared type 'GenericClassIWantToInject'
Why? What have I misunderstood? Is it possible to code this way?
class SomeClass1: SomeBasicProtocol { }
class SomeClass2: SomeBasicProtocol { }
class SomeClass3: SomeBasicProtocol { }
Upvotes: 1
Views: 39
Reputation: 27221
Thanks to @Serj
I've changed my code to this one:
let providerClass = provider.providerClass
switch providerClass {
case is SomeClass1.Type:
let wantedInstance = WantedClass<SomeClass1>()
case is SomeClass2.Type:
let wantedInstance = WantedClass<SomeClass2>()
case is SomeClass3.Type:
let wantedInstance = WantedClass<SomeClass3>()
default: break
}
Now it works.
Upvotes: 0
Reputation: 684
To make things clearer, you have done everything correct except for the last part where you did this let wantedInstance = WantedClass<GenericClassIWantToInject>()
. Lets break down and see what you are trying to do with this line of code. You are trying to tell the compiler at compile time, that WantedClass has a generic parameter that has to be GenericClassIWantToInject
which is computed at run time. Doesn't that sound wrong to you? Can the compiler infer the Type of a generic parameter at compile time with something that is computed at run time? So to answer one of your questions, no you can not use the code this way.
What you can do is something like this:
protocol SomeBasicProtocol {}
class WantedClass<T>: NSObject where T: SomeBasicProtocol {
let generic: T
init(generic: T) {
self.generic = generic
super.init()
}
}
class SomeClass1: SomeBasicProtocol {}
class SomeClass2: SomeBasicProtocol {}
class SomeClass3: SomeBasicProtocol {}
enum Provider: Int {
case one = 1
case two
case three
var providerClass: SomeBasicProtocol {
switch self {
case .one:
return SomeClass1()
case .two:
return SomeClass2()
case .three:
return SomeClass3()
}
}
}
let provider: Provider = .one
let classToInject = provider.providerClass
switch classToInject {
case let class1 as SomeClass1:
let wantedClass = WantedClass(generic: class1)
case let class2 as SomeClass2:
let wantedClass = WantedClass(generic: class2)
case let class3 as SomeClass3:
let wantedClass = WantedClass(generic: class3)
default:
return
}
Now I'm not sure what you want to achieve, but following your example I came up with the code above and that's what I'm guessing you want to do.
Moreover do these changes if you don't need a variable of your generic Parameter in WantedClass
:
class WantedClass<T>: NSObject where T: SomeBasicProtocol {
override init() {
super.init()
}
}
switch classToInject {
case let class1 as SomeClass1:
let wantedClass = WantedClass<SomeClass1>()
case let class2 as SomeClass2:
let wantedClass = WantedClass<SomeClass2>()
case let class3 as SomeClass3:
let wantedClass = WantedClass<SomeClass3>()
default:
return
}
Upvotes: 1