Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can I mix inferred and exlicit generic type parameters in Kotlin?

Assum I have this extension function:

inline fun <reified R> Any.getPrivateProperty(variableName: String): R { … }

I can quite conveniently call this with something like s.getPrivateProperty<Int>("height"), an expression that is of type Int.

Now I wanted to make sure the function is only defined on non-optional types. I used the definitely-not-nullable notation:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

inline fun <T: Any, reified R> T.getPrivateProperty(variableName: String): R { … }

This fulfills the purpose, however, since I have that one type parameter which must be explicit, I actually have to give both now. Example: s.getPrivateProperty<Shape, Int>("height").

Is it even possible to avoid that in general? Is there an alternative way to avoid that here, that is, to only define the extension function over non-optional types?

>Solution :

The first version of the function already does not work on nullable types. For example, this doesn’t compile.

val x: String? = "foo"
val y = x.getPrivateProperty<String>("foo")

In general, when calling a function, you must specify all the type parameters in the <...> part, or you must let all of them be inferred.

There are ways to infer R in this case though. It needs not be always written in <>. Simply do:

val y: String = x.getPrivateProperty("foo")
//     ^^^^^^

That is, since R is the return type, you can just write it as the type of the variable you are assigning to.

For non-return types, if for some reason Kotlin can’t infer them, a simple way to "infer" them is to pass a Dummy<T>, to let the caller specify.

class Dummy<T>

// imagine foo having some other parameters using T and U, 
// but T can't be inferred for whatever reason, but U can be inferred
// you can just add an extra parameter of type Dummy<T>
fun <T, U> foo(... other parameters ..., t: Dummy<T>) { ... }

Then the caller can do:

foo(..., Dummy<SomeType>())

without having to specify U as well.

For non-nullable type parameters, you can use KClass<T> instead of creating your own Dummy<T>.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading