Kotlin NDArray с конструктором лямбда с общим типом возврата

Я пытаюсь создать очень простой общий класс NDArray в Kotlin, который принимает лямбда-выражение как функцию init.

class NDArray<T>(i: Int, j: Int, f: (Int) -> T) { val values: Array<T> = Array(i * j, f) } 

Типичное использование:

 fun main(args: Array<String>){ val m = NDArray(4, 4, ::zero) } fun zero(i: Int) = 0.0 

Моя проблема заключается в том, что компилятор Kotlin жалуется на инициализацию значений в конструкторе

 values = Array(i * j, f) 

говоря: «Невозможно использовать« T »в качестве параметра типа reified. Вместо этого используйте класс». Зачем ?

РЕДАКТИРОВАТЬ:

Если вместо этого заменить реализацию Kotlin Array на свой собственный MyArray, он компилирует:

 class NDArray<T>(i: Int, j: Int, f: (Int) -> T) { val values: MyArray<T> = MyArray(i * j, f) } class MyArray<T>(i:Int, init: (Int) -> T) { ... } 

Не знаете, почему Kotlin относится к MyArray по-другому от обычного массива, когда оба имеют один и тот же конструктор?

    Для создания массива Java необходимо указать тип элемента. В случае вашего класса тип элемента предоставляется только как параметр типа класса, а генерики в Java стираются во время выполнения. Из-за этого тип элемента массива неизвестен, и его невозможно создать.

    Если вы хотите создать пользовательскую оболочку вокруг стандартного Array<T> , это должно выглядеть следующим образом:

     class NDArray<reified T>(i:Int, j:Int, init: (Int) -> T) { val arr = Array<T>(i * j, init) } 

    Ключевое слово reified означает, что ваш T не стирается и может использоваться в тех местах, где нужен настоящий класс, например вызов конструктора Array() .

    Обратите внимание, что этот синтаксис не поддерживается для конструкторов классов, но он по-прежнему полезен для заводских функций (должен быть inline d)

     fun <reified T> arrayFactory(i:Int, j:Int, init: (Int) -> T) = Array<T>(i * j, init) 

    На основе ввода от yole и voddan это лучшее решение, которое я нашел до сих пор:

     class NDArray<T>(val values: Array<T> ){ companion object Factory{ inline operator fun <reified T>invoke(i: Int, j: Int, noinline init: (Int) -> T) = NDArray(Array(i * j,init)) } } 

    Это позволяет использовать reified как конструктор с помощью сопутствующего объекта. Соглашение о создании здания может быть выполнено с использованием оператора invoke. Это работает сейчас:

     fun main(args: Array<String>){ val m = NDArray(4,4, ::zero) } fun zero(i:Int) = 0.0 

    Единственная проблема (за исключением свернутого синтаксиса invoke ()) заключается в том, что конструктор NDArray должен быть общедоступным. Возможно, есть лучший способ?

    ЗАМЕТКА! Следующие проблемы KT-11182 влияет на этот шаблон проектирования