Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiating a generic type in Kotlin

Tags:

kotlin

What's the best way to get an instance of a generic type in Kotlin? I am hoping to find the best approximation of the following C# code:

public T GetValue<T>() where T : new() {     return new T(); } 
like image 533
ikh Avatar asked Apr 18 '17 16:04

ikh


People also ask

Can you instantiate a generic type?

To use Java generics effectively, you must consider the following restrictions: Cannot Instantiate Generic Types with Primitive Types. Cannot Create Instances of Type Parameters.

How do I create a generic type object in Kotlin?

You need to pass a KClass<out Cell> as a constructor parameter to CellList , and to invoke the constructor using reflection. You can also create a factory function with a reified type parameter to enable creating CellList instances with a somewhat cleaner syntax.

How do you declare a generic variable in Kotlin?

We can make generic variable using this kind of syntax: "val destinationActivity: Class<*>". Main part is "*".


1 Answers

EDIT: As mentioned in comments, this is probably a bad idea. Accepting a () -> T is probably the most reasonable way of achieving this. That said, the following technique will achieve what you're looking for, if not necessarily in the most idiomatic way.

Unfortunately, you can't achieve that directly: Kotlin is hamstrung by its Java ancestry, so generics are erased at run time, meaning T is no longer available to use directly. Using reflection and inline functions, you can work around this, though:

/* We have no way to guarantee that an empty constructor exists, so must return T? instead of T */ inline fun <reified T : Any> getValue(): T? {     val primaryConstructor = T::class.constructors.find { it.parameters.isEmpty() }     return primaryConstructor?.call() } 

If we add some sample classes, you can see that this will return an instance when an empty constructor exists, or null otherwise:

class Foo() {} class Bar(val label: String) { constructor() : this("bar")} class Baz(val label: String)      fun main(args: Array<String>) {     System.out.println("Foo: ${getValue<Foo>()}") // Foo@...     // No need to specify the type when it can be inferred     val foo : Foo? = getValue()     System.out.println("Foo: ${foo}") // Foo@...     System.out.println("Bar: ${getValue<Bar>()}") // Prints Bar@...     System.out.println("Baz: ${getValue<Baz>()}") // null } 
like image 133
pdpi Avatar answered Oct 26 '22 04:10

pdpi