How to retrieve items from a generic list in a type safe way

Viewed 1388

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)}
}
3 Answers
Related