Возможно ли объявление массива в Kotlin с размером только при инициализации? - PullRequest
2 голосов
/ 28 июня 2019

Я не нашел, как объявить в Kotlin массив с предопределенным размером без его инициализации.

Это нормально:

lateinit var v:Array<Int>

Но я думаю,что нельзя поместить спецификацию размера в тип массива.

Если нужно указать размер.нужно сделать:

var v2:Array<Int> = Array<Int>(2){5}

В этом случае все элементы вектора равны 5

Ниже приведен пример с классами и массивами:

data class But(
    val fufo: Int=0,
    val tp: Int = 1 
)  
typealias  ArBut = Array<But>
data class CArray (
   var arrayC: ArBut = ArBut(2){But()}
)    
val a =   CArray(arrayOf(But(2,2),But(5,4),But(3,3)))
println(a.arrayC[2])

Это работает!Интересная часть заключается в том, что, поскольку инициализация не является частью типа, вы можете помещать массивы любого размера в класс, не ограничивая проверку.Было бы иначе, если бы размер был частью спецификации типа.

Теперь пример, использующий матрицу.Обратите внимание, что синтаксис немного сложен.

data class CMatr (
   val matrC: Array<ArBut>  = Array<ArBut>(2){ArBut(0){But()}}
)    
 val m =   CMatr(arrayOf( arrayOf(But(2,2),But(5,4)),   
         arrayOf(But(-2,2),But(3,4)), arrayOf(But(1,1),But(5,3))  ))
 println(m.matrC[2][1])  // Also works! 

Невозможно указать размер в спецификации типа массива или я что-то упустил?

Ответы [ 3 ]

3 голосов
/ 28 июня 2019

для примитивных типов:

это то, как вы это делаете.вместо использования встроенных функций kotlin, таких как intArrayOf(args...), вы используете конструктор для IntArray

. Вот пример:

// Array of integers of a size of N
val arr = IntArray(N)

// Array of integers of a size of N initialized with a default value of 2
val arr = IntArray(N) { 2 }

для ссылочных типов:

для объектов ссылочного типа вы можете сделать

val cars: Array<Car?> = arrayOfNulls(N) 
//returns an array of nullable Car objects with null values and size of N

, и если вы хотите получить массив ненулевых объектов, вам нужно инициализировать их при создании массива

val cars: Array<Car> = Array<Car>(5){ Car() } 
//returns an array of non nullable car objects that has been initialized 
//with the method you provided in this case Car constructor with size of N
1 голос
/ 29 июня 2019

Да, размер массива не является частью его типа в Kotlin, и нет способа сделать его частью. Это не только для массивов; типы никак не могут зависеть от значений в Kotlin.

Инициализация размера в типе позволяет проверять нарушение границ во время выполнения.

Границы массива всегда проверяются во время выполнения на JVM. Даже если компилятор не хочет этого делать, он не может.

1 голос
/ 28 июня 2019

Для вашего примера, с классом But, вы можете использовать:

var arrayC: Array<But?> = arrayOfNulls(2) // no initialization required

или

var arrayC: Array<But> = Array<But>(2){But()} // initialization required

Но в любом случае вы не помешаете создать новый экземпляр большего массива и присвоить его переменной.

EDIT

На мой взгляд, есть два подхода к решению этой проблемы.

Первым было бы объявить свойство массива как var и проверить присваивание в вашем установщике:

class Test {
    var array: Array<Int> = Array(3){0}
        set(value) {
            if(value.size > 3)
                throw IllegalArgumentException("The array size cannot be bigger than 3")

            field = value
        }
}

fun main(args: Array<String>) {
    val test = Test()
    test.array = arrayOf(0, 1, 2) // Ok
    test.array = arrayOf(0, 1, 2, 3) // throws IllegalArgumentException

}

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

class Test {
    val array: Array<Int> = Array(3){0}
}

fun main(args: Array<String>) {
    val test = Test()

    for (i in 0..2) // Ok
        test.array[i] = i

    for (i in 0..3) // throws ArrayIndexOutOfBoundsException
        test.array[i] = i

    test.array = arrayOf(0, 1, 2, 3) // compile time error: Val cannot be reassigned
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...