Reputation: 381
I'm trying to use the generic type of a class in another class that uses this one:
Kotlin
class Callback <O> ()
class Controller <E> (callback: E) where E: Callback<O> {
fun foo1 (a: O) {...}
fun foo2 (): O {...}
}
Java
class Callback <O> {}
class Controller <E extends Callback<O>> {
Controller(E callback) {}
public void foo1(O a) {...}
public O foo2() {...}
}
An easy solution is to declare both types E and O on the Controller class in this way:
Kotlin
class Controller <E, O> (callback: E) where E: Callback<O> { ... }
Java
class Controller <E extends Callback<O>, O> { ... }
However, I want to avoid to declare both types on the constructor because the information is repeated and it is not so pretty.
I need the type E
on the constructor because I need to define functions such as:
class StringCallback: Callback<String>() { ... }
fun example(callbackParam: Controller<StringCallback>) { ... }
I want the object callbackParam
uses my defined StringCallback
, not any Callback<String>
.
And remember that I also need the O
type in theController
class to operate with this type. Can I "extract" or "infer" it without declaring it in the generic constructor?
[@LppEdd with your permission I'll use your class :) ]
Any idea?
Thanks in advance!!
Upvotes: 2
Views: 1866
Reputation: 21104
What you can do is
class Controller<E> {
private final Callback<E> callback;
Controller(final Callback<E> callback) {
this.callback = callback;
}
public void foo1(final E a) { callback.set(a); }
public E foo2() { return callback.get(); }
}
Example:
final Controller<String> stringController = new Controller<>(new Callback<>());
That's because you already know you'll accept a Callback<?>
.
There is no need to use E extends Callback
. But keep reading
This
Controller(final Callback<? extends E> callback)
means the constructor will accept every type which is a subtype of Callback<E>
class StringCallback extends Callback<String> { ... }
class IntegerCallback extends Callback<Integer> { ... }
final Controller<String> c1 = new Controller<>(new StringCallback());
final Controller<Integer> c2 = new Controller<>(new IntegerCallback());
Upvotes: 2
Reputation: 19926
You don't need to know the type of the Callback
just that it's generic parameter is E
.
So you can declare your class in Kotlin like this:
class Controller<O>(callback: Callback<O>) { ... }
And in java like this:
public class Controller<O> {
public Controller(Callback<O> callback) { ... }
}
Declaring the type of the Callback
to be generic would only make sense if you'd allow the caller of your controller to explicitly interact with the callback. But from your given code you just return or accept values from / to the callback.
Upvotes: 2
Reputation: 4982
You may shorten the code:
class Controller<E : Callback<O>, O> (callback: E) { .. }
But it will not let you a chance to get rid of the second generic parameter. You use the O
type in the functions of your class.
You may try to say class Controller<E: Callback<*>>
or class Controller<E : Callback<Any>>
if you do not need the actual O
type in the code of the Controller
class.
Using the Callback<Any>
may require to declare the Callback
type parameters with variance. In Kotlin one defines variance at the declaration level. See
https://kotlinlang.org/docs/reference/generics.html#declaration-site-variance
for more details.
Upvotes: 1