我有以下类似的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的子类型”
但我知道如何解决它。下面的A
和B
扩展ClassA
并实施InterfaceA
。
val someClass = SomeClass(A(), B())
有人可以帮忙吗?
答案 0 :(得分:4)
您可以使用where-clause来定义多个上限:
class SomeClass<T>(a: T, b: T)
where T : ClassA, T : InterfaceA
更新,因为显然这不是问题。假设您拥有上面的代码(或原始Java),并且ClassB
继承/实现T
,ClassA
和{{}所需的两种类型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中没有问题,因为A
和B
都是ClassA
和InterfaceA
的子类。
但它可以通过为多个上限通用参数编写一个丑陋的方法来实现自己的方式。例如:
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 ---^
}
上面的代码没有问题,因为F
和S
的原始类型都是ClassA
和InterfaceA
所以它在运行时运行正常和type inference&amp; type erasure仅发生在编译时中。