I've been reading up on Kotlin generics for a while and came to a sense that it's a very powerful feature of the language.
This made me wonder and experiment, and I can't figure out a nice solution to the following problem. Say I have the following code:
interface WidgetProducerConsumer<T> {
fun produce(): Widget<T>
fun consume(widget: Widget<T>)
companion object {
fun getStringWidgetProducerConsumer(): WidgetProducerConsumer<*> {
return StringWidgetProducerConsumer()
}
}
}
data class Widget<T>(val contents: T)
private class StringWidgetProducerConsumer: WidgetProducerConsumer<String> {
override fun produce(): Widget<String> {
return Widget("hello world")
}
override fun consume(widget: Widget<String>) {
// Do something with string here, since we know it can only be a sting
println(widget.contents)
}
}
And in another part of my project I wanted to do something like:
val producerConsumer = WidgetProducerConsumer.getStringWidgetProducerConsumer()
// Can't do this with WidgetProducerConsumer<*> because the consumed type is Nothing
// and returned type is Any?
producerConsumer.consume(producerConsumer.produce())
I would naturally not be able to, since at the use site the star projection turns the T into their highest Any? and lowest Nothing bounds as it is intended to do.
I want to make sure that the implementation of WidgetProducerConsumer takes only Widgets that it itself produces. This would allow me to inject specific implementations of the WidgetProducerConsumer without exposing information about the internal minutiae to the consumer. Is there a pattern or recipe for it?
Intuitively it feels like there should be a nice way to achieve this without resorting to type checks, casting and alike, however I can't figure it out.