I have a Building class that represents an array of Room objects. Each room has some properties which are irrelevant for now.
I am getting the rooms from user input like this:
- First-line is the number of rooms.
- The next n lines give information about the rooms in this format:
"[room index] [room properties...]". The index of each room ranges from 0 to n -1.
Example input:
3
0 [room 0 properties: a, b]
2 [room 2 properties: x, y]
1 [room 1 properties: u, v]
which should create the object:
Building: rooms: [Room(a, b), Room(u, v), Room(x, y)]
I can't guarantee that the rooms will be given in order, but I can promise that all rooms will be given as input. If I was in Java, I could easily write code like this:
Scanner in = new Scanner(System.in);
Room[] rooms = new Room[in.nextInt()];
for (int i = 0; i < rooms.length; i++) {
int roomIndex = in.nextInt();
// Get room properties from rest of line input
rooms[roomIndex] = new Room(...);
}
However, in kotlin, there is a little problem with this approach: I have to initialize the rooms array when I create it. I can't create an uninitialized array, like in Java, and then initialize it in a loop. The Array constructor in kotlin takes a size and a lambda parameter to initialize the array in the order of the indices. As I said, I can't promise the input will be given in the order of indices. I can only promise that all rooms will be given and initialized.
I can create an array of nullable rooms (Array<Room?>), but I don't like this idea because all rooms will be given, so null checks and assertions will be useless when using the array later.
Is there a way to create an uninitialized array in kotlin, and tell the compiler not to freak out about this because I promise the array will be fully initialized after the loop runs?
I didn't find a way to cast an Array<Room?> to Array<Room> without creating a copy of the array, which seems wasteful for me. I also don't think I can use something like Array<lateinit Room> as I can do with regular non-collection properties. The only solution I came up with is to initialize the array with a dummy Room object and then actually initialize it in the loop:
val dummy = Room(...) // dummy object with useless properties
val rooms = Array(size) { dummy }
// Real initialization in a loop
repeat(rooms.size) {
val properties = readline()!!.split(' ')
val roomIndex = properties[0].toInt()
// Parse rest of properties
rooms[roomIndex] = Room(...)
}
What is the best way to create such an array? I don't think I should use Array<Room?> because I can promise every element of the array will be non-null after the loop, and I don't like the idea of a dummy object, but it might be the best bet? Do you have another suggestion?
Thanks in advance.