2
votes

La déclaration de tableau dans Kotlin avec une taille est-elle possible uniquement avec l'initialisation?

Je n'ai pas trouvé comment déclarer dans Kotlin un tableau avec une taille prédéfinie sans l'initialiser.

C'est OK:

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! 

Mais je suppose qu'on ne peut pas mettre une spécification de taille dans le type de tableau.

Si l'on a besoin de spécifier une taille. il faut faire:

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])

Dans ce cas, tous les éléments du vecteur sont égaux à 5

Ci-dessous il y a un exemple avec des classes et des tableaux:

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

Cela fonctionne! La partie intéressante est que comme l'initialisation ne fait pas partie du type, vous pouvez placer des tableaux de n'importe quelle taille dans la classe sans vérification de limite. Ce serait différent si la taille faisait partie de la spécification de type.

Maintenant, un exemple, en utilisant la matrice. Notez que la syntaxe est un peu complexe.

lateinit var v:Array<Int>

Est-il impossible de mettre la taille dans la spécification du type de tableau ou il me manque quelque chose?


0 commentaires

3 Réponses :


3
votes

pour les types primitifs:

voici comment procéder. au lieu d'utiliser des fonctions intégrées de kotlin comme intArrayOf (args ...) vous utilisez le constructeur pour IntArray

voici l'exemple: p>

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

pour les types de référence:

pour les objets de type référence que vous pouvez faire

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

et si vous voulez un tableau d'objets non nuls, vous devez les initialiser lors de la création du tableau

// 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 }


3 commentaires

C'est correct, mais juste pour certains types primitifs ( Byte , Float , Double , Int , Long , Char et, Boolean ). Pas String . Votre deuxième exemple peut être écrit un val arr = IntArray (N) {2}


@Pauloedralsbaum Pour les tableaux de référence, utilisez quelque chose comme val arr = Array (N) {""} ou val arr = Array (N) {null}


Oui, mais mon point est de permettre aux programmeurs de choisir la taille du tableau dans la partie de type déclaration et non dans la partie d'initialisation. Il protège les programmeurs contre les affectations erronées liées à la taille du tableau.



1
votes

Pour votre exemple, avec la classe But , vous pouvez utiliser:

var arrayC: Array = arrayOfNulls (2) // aucune initialisation requise code >

ou:

var arrayC: Array = Array (2) {But ()} // initialisation requise p>

Mais dans les deux cas, cela ne vous interdira pas de créer une nouvelle instance d'un plus grand tableau et de l'assigner à la variable.

EDIT

À mon avis, il existe deux approches pour résoudre ce problème.

La première serait de déclarer votre propriété de tableau en tant que var et de tester l'affectation dans votre setter:

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
}


2 commentaires

Oui, je sais, mais je crois que ce serait un choix utile pour les programmeurs de sélectionner la taille dans le type et non par l'initialisation. L'initialisation de la taille dans le type permet de vérifier la violation liée au runtime. Cela pourrait faire partie de la définition de type, évitant les erreurs logiques. C'est vraiment arrivé dans mon projet.


Je vois. J'ai modifié ma réponse pour ajouter quelques solutions possibles



1
votes

Oui, la taille du tableau ne fait pas partie de son type dans Kotlin et il n'y a aucun moyen d'en faire une partie. Ce n'est pas spécifique aux tableaux; les types ne peuvent en aucun cas dépendre des valeurs dans Kotlin.

L'initialisation de la taille dans le type permet de vérifier la violation des limites lors de l'exécution.

Les limites des tableaux sont toujours vérifiées lors de l'exécution sur JVM. Même si un compilateur ne voulait pas le faire, il ne le peut pas.


2 commentaires

Je sais que les limites du tableau sont vérifiées lors de l'exécution, mais à un autre moment. Lorsque vous attribuez un tableau plus long que ce qui est projeté, il n'y a pas d'archivage possible dans Kotlin . Évidemment, lorsque vous essayez d'utiliser un composant en dehors des index existants, chaque langue donnera (pratiquement) une erreur. Les anciens langages pourraient être de faire une vérification du compilateur des tableaux de taille tant que les tailles utilisées étaient des constantes (donc connues au temps du compilateur)


Imaginez une structure avec un tableau de tableaux de points 3D. À moins que vous ne définissiez la 3D avec une classe, il n'y a aucun moyen de définir au moment du compilateur que chaque point a une longueur de 3.