Почему переведенный код Котлина жалуется на массив<BaseData>? быть массивом<out BaseData>
Наличие java-класса, использование androidStudio для перевода на kotlin. Получил ошибку и не уверен, как правильно ее перевести.
Java-код:
public class BaseDataImpl extends BaseData {
private final BaseData[] translators;
public BaseDataImpl(final BaseData... translators) {
this.translators = cloneArray(translators);
}
public static <T> T[] cloneArray(final T[] array) {
if (array == null) {
return null;
}
return array.clone();
}
}
после перевода кода получена ошибка: required Array<BaseData>?, found Array<out BaseData>
, но translators
в cloneArray<BaseData>(translators)
вызов определяется как val translators: Array<BaseData>?
,
кто-нибудь может помочь объяснить?
class BaseDataImpl(vararg translators: BaseData) : BaseData() {
private val translators: Array<BaseData>?
init {
this.translators = cloneArray<BaseData>(translators) //<=== error: required Array<BaseData>?, found Array<out BaseData>
}
companion object {
fun <T> cloneArray(array: Array<T>?): Array<T>? {
return array?.clone()
}
}
}
1 ответ
Это написано в справочнике функций Kotlin относительно varargs:
Внутри функции vararg-параметр типа
T
виден как массивT
то естьts
переменная в приведенном выше примере имеет типArray<out T>
,
где указанная функция была:
function <T> asList(vararg ts: T): List<T>
Так что в вашем случае вы на самом деле передать Array<out BaseData>
но вы принимаете только массив типа Array<T>?
(в твоем случае Array<BaseData>
). Либо вы адаптируете все типы к Array<out T>
(что в основном похоже на высказывание List<? extends BaseData>
в Java) или вы заботитесь о том, что вы имеете дело только с T
s вместо, например:
inline fun <reified T> cloneArray(array: Array<out T>?): Array<T>? {
return array?.clone()?.map { it }?.toTypedArray()
}
Но посмотрите документацию, касающуюся этого: эталонные прогнозы Kotlin. Вы, вероятно, можете сделать это еще проще.