Reputation: 179
I use an in-house Java framework containing the following classes (simplified for demonstration):
public interface SomeAction<T, R> {
R run(T t);
}
public class ConcreteAction implements SomeAction<Integer, String> {
@Override
public String run(Integer arg) {
return "abc";
}
}
public class ActionFactory {
public <A extends SomeAction<T, R>, T, R> SomeAction<T, R> create(Class<A> clz) throws IllegalAccessException, InstantiationException {
return clz.newInstance();
}
}
Calling the factory method from Kotlin in a java-way works ok:
ActionFactory().create(ConcreteAction::class.java).run(1)
Then I created the following extension method to make it more concise:
inline fun <reified A : SomeAction<T, R>, T, R> ActionFactory.create(): SomeAction<T, R> {
return create(A::class.java)
}
But a call to ActionFactory().create<ConcreteAction>().run(1)
fails with the error 3 type arguments for inline fun ...
Are there any ways to make it work without touching the java code?
Upvotes: 0
Views: 273
Reputation: 170713
Note: this may not work with actual code depending on what exactly you simplified out. But given this setup, it may be reasonable to assume that the return value of create
will actually be an instance of A
, in which case
inline fun <reified A : SomeAction<*, *>> ActionFactory.create(): A {
return create(A::class.java) as A
}
ActionFactory().create<ConcreteAction>().run(1)
will work. The assumption should be documented and tests added if you go that way!
Upvotes: 0
Reputation: 5002
Kotlin does not allow calling a generic function while specifying only a part of the type parameters. If you want to call create
with explicit type parameters, you have to specify all three of them:
ActionFactory().create<ConcreteAction, Int, String>().run(1)
Upvotes: 2