I have issues with Kotlin generics system. I cannot figure out how to define constructor in kotlin to make it compilable. As far as I know similar example would work in Java, but it does not in Kotlin.
I doubt the first code sample would work in Java. ProxyIterator requires a mapper that should be able to accept Any? objects, but you provide a function that does not work with Any?, but only with integers.
But I get your point about X type that is only needed when constructing the object and then it is redundant. One solution is to create interface with T only and private implementation with both T and X. Then you need a function parameterized with both T and X, but returning object with only T. Maybe there is a better solution.
If your ProxyIterator does not provide anything more than just Iterator, then you can make it simpler, treating ProxyIterator as this private implementation. Just make it private and then add this function:
No, it shouldn’t. ProxyIterator says it will provide Any? objects to the mapper function. It could be an integer, it could be a sheep. Now, your mapperFun() can only work with integers, not with sheep. Therefore, it doesn’t fit in this place. The opposite would work: ProxyIterator would require (Int) -> Iterable<T> and you would provide a function that accepts Any?.
If you need this ProxyIterator type then do it like this:
I guess you deleted your post with Java example after you discovered it stops working when the mapper receives Integer, not Object
Look, this is pretty easy, but you need to understand what is the data flow here. Let’s make a simpler example:
fun main() {
outer(::inner)
}
fun outer(func: (Any?) -> Unit) {
func("hello")
}
fun inner(value: Int) {}
func in outer() receives Any?, meaning that it can be invoked with any possible object. So outer() invokes it passing a String. String is Any?, so func should handle it just right. Now, we pass inner as func. But wait… as a result we do something like this: inner("hello") which doesn’t make sense, because inner() can only accept integers. This is why outer(::inner) does not compile.
(Int) -> Unit can’t be safely cast to (Any?) -> Unit. The opposite is fine.
I don’t want to start talking about variance, because it will only make things more complicated. But the point is: casting (Int) -> Unit to (Any?) -> Unit is actually like casting Any? to Int. That’s because Any?/Int is consumed here, not produced.
Yes, I noticed that we (probably?) can’t generalize the constructor in Kotlin. This is why I suggested using additional function instead of constructor. It can be a top level function, it can be a member of companion object. Other than that, I think you can do the same in Kotlin, as in Java.
I mean, if you only need this X in the constructor and then you don’t use it internally in ProxyIterator, then you don’t even have to create a separate ProxyIterator<T> and ProxyIteratorImpl<X, T> as I suggested. Just do exactly as you would in Java, but move the code from the constructor to the external function (and make the constructor private). I think it should be fine. You can even name your function ProxyIterator() create invoke operator in the companion and then it feels almost like the constructor