我怎样才能实现像A这样的java类:extends B在kotlin中实现C

时间:2017-06-19 09:20:44

标签: java generics kotlin

我有以下类似的java类:

public class SomeClass<T extends ClassA & InterfaceA> {

    public SomeClass(T a, T b) {}

}

class A extends ClassA implements InterfaceA{}
class B extends ClassA implements InterfaceA{}

我正在尝试在下面的kotlin中创建SomeClass的实例,但是我收到了编译错误:

“感染类型Any!不是ClassA的子类型”

但我知道如何解决它。下面的AB扩展ClassA并实施InterfaceA

val someClass = SomeClass(A(), B()) 

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:4)

您可以使用where-clause来定义多个上限:

class SomeClass<T>(a: T, b: T)
    where T : ClassA, T : InterfaceA

更新,因为显然这不是问题。假设您拥有上面的代码(或原始Java),并且ClassB继承/实现TClassA和{{}所需的两种类型1}}。

InterfaceA

如果某个地方有open class ClassA interface InterfaceA class ClassB : ClassA(), InterfaceA SomeClass a类型的b,则创建T的实例(例如,他们是&#39;然后ClassB)的实例如下所示:

val a = ClassB()
val b = ClassB()
val someClass = SomeClass(a, b)

包含类型参数的最后一行的长格式实际上看起来像这样(但是大多数时候可以推断出类型参数,就像你上面所见):

val someClass = SomeClass<ClassB>(a, b)

再次编辑:

如果您需要传递符合类型要求的不相关类的实例,则需要提供SomeClass两个类型参数:

public class SomeClass<T1 extends ClassA & InterfaceA, T2 extends ClassA & InterfaceA> {

    public SomeClass(T1 a, T2 b) {}

}

答案 1 :(得分:0)

在Kotlin中有多个上限的泛型是痛苦的。也许这是一个错误,java中没有问题,因为AB都是ClassAInterfaceA的子类。 但它可以通过为多个上限通用参数编写一个丑陋的方法来实现自己的方式。例如:

val error = SomeClass(A(), B());
val ok = new(A(), B());

//star projection means: <? extends ClassA & InterfaceA>
//                                             |
fun <F, S> new(first: F, second: S): SomeClass<*>
        where F : ClassA, F : InterfaceA,
              S : ClassA, S : InterfaceA {

    @Suppress("UNCHECKED_CAST")
    return SomeClass(first,second as F);
    //           it is always ok  ---^
}

上面的代码没有问题,因为FS的原始类型都是ClassAInterfaceA所以它在运行时运行正常type inference&amp; type erasure仅发生在编译时中。