IMHO this can be solved in most cases with either:
- a “companion” inline function, with the same name as the class, when the type parameter is to be chosen by the user (Foo)
- a constant argument, when the type parameter is fixed by the subclass (StringFoo)
@Suppress("FunctionName")
inline fun <reified T> Foo() = Foo(T::class.java)
open class Foo<T>(private val type: Class<T>) {
val name: String get() = type.name
fun newInstance(): T = type.newInstance()
}
class StringFoo : Foo<String>(String::class.java)
fun main() {
println(Foo<Int>().name) // java.lang.Integer
println(StringFoo().name) // java.lang.String
}