Reputation: 31
I'd like variable f to be as the same type of the generic parameter F, but I can't declare f in the constructor of the class.
class myClass<F: myInterface>(
private val v1: String,
private val v2: String,
){
f.methodOfMyInterface()
}
Upvotes: 0
Views: 374
Reputation: 18617
You can simply declare f
as being of type F
, e.g.:
class MyClass<F: MyInterface>(/*…*/) {
val f: F = /*…*/
}
It doesn't matter that F
isn't known at compile-time: the compiler will ensure it all works out at run-time.
(If you're interested in how it's implemented: in Java and Kotlin, generics like this are implemented by type erasure, which means that the compiled bytecode knows nothing about F
. It simply uses the relevant upper bound on the type, which in this case is MyInterface
. The compiler makes sure that it's only used in a type-safe way.)
When creating an instance, you'll need to give the compiler a clue as to what type F
is. You could do it directly, e.g.:
val myClass = MyClass<SomethingImplementingMyInterface(/*…*/)
Or you could specify the resulting type:
val myClass: MyClass<SomethingImplementingMyInterface> = MyClass(/*…*/)
Or one of the parameters could mention that type. For example, if the class were:
class MyClass<F: MyInterface>(val f: F)
then the compiler could infer it from that:
val myClass = MyClass(SomethingImplementingMyInterface())
(Note: I'd be very wary about using reflection. It's great for tools, plug-ins, and other special cases; but for general application code, it's rarely necessary, as well as being slow and usually not type-safe. There's usually a better design that avoids it.)
Upvotes: 1
Reputation: 1605
I'm not fully certain that this fulfils your needs, but this is probably as close as you can get:
interface Test
class ImplTest : Test
class Data<T : Test>(factory: () -> T) {
val t: T = factory()
}
inline fun <reified T : Test> data(): Data<Test> {
return Data { T::class.java.newInstance() }
}
Then you can invoke:
data<ImplTest>()
And this will return you a Data
object, which will have an instance of ImplTest
assigned to the t
field.
Assumptions:
T
is has an empty constructor.Upvotes: 0