I am trying to implement a parameterized Queue backed by an Array. Just a simple exercise to get more fluent with generics in Kotlin:
class Queue<T>(val size: Int = 1000) {
private var count = 0
private var front = 0
private var back = 0
private val queue = Array<Any?>(size) { null } // Here's what's bugging me
fun enqueue(new: T) {
if (count >= size) throw Exception("Queue is full")
queue[back] = new
back = if(back == size-1) 0 else back+1
count++
}
@Suppress("UNCHECKED_CAST") // And I don't like this
fun dequeue(): T? {
if (isEmpty()) return null
val res: T = queue[front] as T
front = if (front == size-1) 0 else front+1
count--
return res
}
@Suppress("UNCHECKED_CAST")
fun peek(): T? {
return if (isEmpty()) null else queue[front] as T
}
private fun isEmpty() = count == 0
}
This compiles and runs (but I'm wary):
fun main() {
val queue = Queue<Int>(size = 2)
queue.enqueue(4)
queue.enqueue(5)
println(queue.peek()) // 4
println(queue.dequeue()) // 4
println(queue.peek()) // 5
queue.enqueue(6)
queue.enqueue(7) // Exception: Queue is full
}
I'm pretty confident that this implementation is safe and functional, but I really don't like suppressing the UNCHECKED_CAST inspection (nor do I want to leave the warnings).
I have read documentation and articles about generics, and I think I'm following the concepts. But nobody seems to be trying to do anything like this in the examples I've found. I would prefer to make my member queue
an Array<T?>, but I understand that at runtime, T
won't be known because of Type Erasure.
Is there a better way to do this? Or is it better not to do? Would this raise red flags if I did this in an interview?