I'd like to put items in a generic container but retrieve them in a type safe manner. The container will tag each item with a sequence number when it's added. I tried to implement this in Kotlin but ran into problems in the pens() method. Is there a way to use type information in a function argument to define the type of the return value?
import java.util.concurrent.atomic.AtomicInteger
import kotlin.reflect.KClass
interface Item
data class Pen(val name: String) : Item
data class Eraser(val name: String) : Item
data class Ref<out T : Item> (val id: Int, val item: T)
class Container<T: Item> {
private val seq = AtomicInteger(0)
private val items: MutableList<Ref<T>> = mutableListOf()
fun add(item: T) = items.add(Ref(seq.incrementAndGet(), item))
fun filter(cls: KClass<*>) : List<Ref<T>> = items.filter{cls.isInstance(it.item)}.toList()
// to retrieve pens in a type safe manner
// Type mismatch required: List<Ref<Pen>> found: List<Ref<T>>
fun pens(): List<Ref<Pen>> = filter(Pen::class)
}
fun main(args: Array<String>) {
val container = Container<Item>()
container.add(Pen("Pen-1"))
container.add(Pen("Pen-2"))
container.add(Eraser("Eraser-3"))
container.add(Eraser("Eraser-4"))
// the filter method works
container.filter(Pen::class).forEach{println(it)}
}