У меня есть классы 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{}
Я пытаюсь создать экземпляр SomeClass в kotlin ниже, но я получаю ошибку компиляции:
«infered type Any! не является подтипом ClassA"
но я знаю, как это исправить. A
и B
ниже расширяет ClassA
и реализует InterfaceA
.
val someClass = SomeClass(A(), B())
Может ли кто-нибудь помочь в этом?
Вы можете использовать предложение where для определения нескольких верхних границ:
class SomeClass<T>(a: T, b: T) where T : ClassA, T : InterfaceA
Обновление, поскольку, видимо, это был не вопрос. Предположим, у вас есть код выше (или оригинальная Java) и ClassB
который наследует / реализует два типа, которые требуются от T
, ClassA
и InterfaceA
.
open class ClassA interface InterfaceA class ClassB : ClassA(), InterfaceA
Создание экземпляра SomeClass
если у вас есть a
и b
типа T
откуда-то (например, это экземпляры ClassB
), выглядит следующим образом:
val a = ClassB() val b = ClassB() val someClass = SomeClass(a, b)
Длинная форма последней строки с включенным параметром типа действительно выглядит так (но параметр типа можно вывести большую часть времени, как вы видели выше):
val someClass = SomeClass<ClassB>(a, b)
Изменить снова:
Если вам нужно передать экземпляры несвязанных классов, которые соответствуют требованиям типа, вам нужно SomeClass
параметры вашего типа SomeClass
:
public class SomeClass<T1 extends ClassA & InterfaceA, T2 extends ClassA & InterfaceA> { public SomeClass(T1 a, T2 b) {} }
Общий с множественными верхними границами в Котлине болезнен. возможно, это ошибка, в 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
поэтому он отлично работает во время выполнения , а тип erference type type type type только во время компиляции .