The code:
abstract class DataContainer(public val path: String)
val preloaded: MutableMap<Class<out DataContainer>, HashSet<out DataContainer>> = hashMapOf()
I would like to know how to make Kotlin realize that the first out DataContainer is the same type as the second out DataContainer.
So that code like:
fun <D: DataContainer> get(clazz: Class<D>): HashSet<D> = preloaded[clazz] as HashSet<D>
Doesn't require as HashSet<D> (and isn't prone to casting errors).
I am new to Kotlin, so do link documentation if I've missed something.
Also, this code would be inside an object if it matters.
I don't think that what you want is feasible at a language level.
A cast in the get method isn't that bad as long as you can do it safely. The only way I can see to do that safely is to control the put method as well.
If you enforce that each key of type D : DataContainer will be paired with a key of type Set<D>, you can safely cast when getting. For instance you could something like this:
object DataContainerRegistry {
private val preloaded: MutableMap<Class<out DataContainer>, HashSet<DataContainer>> = hashMapOf()
fun put(dataContainer: DataContainer) {
val set = preloaded.getOrDefault(dataContainer::class.java, HashSet())
set.add(dataContainer)
preloaded[dataContainer::class.java] = set
}
fun <D : DataContainer> get(clazz: Class<D>) = preloaded.getOrDefault(clazz, HashSet()) as Set<D>
}
The limitations of this method are:
DataContainerRegistry singleton in my example) will have direct access to the preloaded map get method will return only Set, not the mutable interface. This way you know that nobody will mess up preloaded and each Set contained in it, and you can then cast light-heartedly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With