Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoking a method with a generic type in Kotlin with multiple parameter type constraints

I have the following interface method definition written in Java:

<T extends View & ISpecificView> T getSpecificView();

A Java-based consumer code is able to operate on this method simply by invoking it and treat the returned value as an object extending the View class and implementing the ISpecificView interface the following way:

getContainer().getSpecificView().whateverTclassMethod()

Trying to invoke the same code in Kotlin I get the Type inference failed: Not enough information to infer parameter T (...) Please specify it explicitly error on the getSpecificView() method. I'd love to provide the type explicitly, but I'm unable to pass any specific class, since it may be any ancestor of the View class that implements the ISpecificView interface. Passing either single View or ISpecificView does not help - it results in the Type argument is not within its bounds. Expected: View! Found ICustomView and vice versa.

Is there any possibility to pass an equivalent to Java's T extends View & ISpecificView in Kotlin while calling a method, so I can make use of it?

like image 607
mrpasqal Avatar asked Apr 01 '19 21:04

mrpasqal


People also ask

How do I call generic method Kotlin?

Kotlin generic example When we call the generic method <T>printValue(list: ArrayList<T>) using printValue(stringList), the type T of method <T>printValue(list: ArrayList<T>)will be replaced by String type.

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 "*".

What is the difference between * and any in Kotlin generics?

When we define a collection with "*", it should contain the object of only that type. There should not be any mix and match between the data types inside a collection. If we use "Any", we can mix and match the data types, which means we can have multiple data types in a collection.

What is in and out in Kotlin generics?

In the event one generic class uses the generic type as input and output to it's function, then no in or out is used. It is invariant.


1 Answers

To recap (and I hope I got the question right!), in Java you can do

final View view = getContainer().getSpecificView();  // or
final ISpecificView iview = getContainer().getSpecificView();

In Kotlin the same thing

val view: View = getContainer().getSpecificView()

results in Type inference failed: Not enough information to infer parameter T


After 50 minutes of trying and trying...
Just create a dummy class (abstract?)

abstract class KView : View(), ISpecificView

And use it to explicitly set a generic return type

val view: View = getContainer().getSpecificView<KView>()
view.whateverClassMethod()

val iview: ISpecificView = getContainer().getSpecificView<KView>()
iview.whateverInterfaceMethod()

// or just

(getContainer().getSpecificView<KView>() as View).whateverClassMethod()
(getContainer().getSpecificView<KView>() as ISpecificView).whateverInterfaceMethod()

A specific cast to View or ISpecificView is required, because if you just do

getContainer().getSpecificView<KView>()

you'll get

class your.package$ExtendingClass cannot be cast to class your.package.KView

but that's is perfectly fine.
Even in Java you need to decide if you want a View or an ISpecificView.


This way you'll be able to operate on all the methods of View or ISpecificView.


Really, I don't know what else to try. Hope someone comes up with something better.

Edit: if what you mean is in Java you do

final ExtendedView ev = getContainer().getSpecificView();

well, this is a bit wrong imho, even if it compiles, as you cannot guarantee the return type is really ExtendedView. You just know for sure it extends View and implements ISpecificView.

like image 75
LppEdd Avatar answered Sep 21 '22 11:09

LppEdd