在通用类中使用类的子类型

时间:2019-03-08 12:02:08

标签: java generics 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() {...}
}

一个简单的解决方案是以这种方式在Controller类上声明类型E和O:

科特林

class Controller <E, O> (callback: E) where E: Callback<O> { ... }

Java

class Controller <E extends Callback<O>, O> { ... }

但是,我想避免在构造函数上同时声明这两种类型,因为信息是重复的,而且不太漂亮。

编辑

我需要在构造函数上使用类型E,因为我需要定义以下函数:

class StringCallback: Callback<String>() { ... }

fun example(callbackParam: Controller<StringCallback>) { ... }

我希望对象callbackParam使用我定义的StringCallback,而不是任何Callback<String>

请记住,我还需要O类中的Controller类型来使用这种类型。我可以在没有在通用构造函数中声明的情况下“提取”或“推断”它吗?

[@ LppEdd,您的允许,我将使用您的课程:)]

有什么主意吗?

提前谢谢!

3 个答案:

答案 0 :(得分:2)

你能做的是

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(); }
}

示例:

final Controller<String> stringController = new Controller<>(new Callback<>());

那是因为您已经知道您会接受Callback<?>
无需使用E extends Callback。但请继续阅读

Controller(final Callback<? extends E> callback)

表示构造函数将接受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());

答案 1 :(得分:2)

您不必知道Callback的类型,只需知道其通用参数为E即可。

因此您可以像这样在Kotlin中声明您的课程:

class Controller<O>(callback: Callback<O>) { ... }

在Java中是这样的

public class Controller<O> {
    public Controller(Callback<O> callback) { ... }
}

仅当您允许控制器的调用者与回调显式交互时,才将Callback的类型声明为通用。但是从给定的代码中,您只需从/返回值或接受值即可。

答案 2 :(得分:1)

您可以缩短代码:

class Controller<E : Callback<O>, O> (callback: E) { .. }

但是,它不会让您有机会摆脱第二个通用参数。您可以在类的函数中使用O类型。

如果在class Controller<E: Callback<*>>类的代码中不需要实际的class Controller<E : Callback<Any>>类型,则可以尝试说OController

使用Callback<Any>可能需要声明具有差异的Callback类型参数。在Kotlin中,在声明级别定义了方差。看到 https://kotlinlang.org/docs/reference/generics.html#declaration-site-variance
有关更多详细信息。