Sometimes I want to have an extension function on a generic type, whose parameter or return value is a subtype of the given type parameter, but without having to specify that actual type parameter. (maybe, if it isn't clear, the code will clarify it better?)
Using the signature of this answer:
inline fun <reified U : T, T> Iterable<T>.partitionByType(): Pair<List<U>, List<T>>
It forces me to use it as follows:
val list : List<SomeType>
list.partitionByType<InterestedType, SomeType>()
However, what I rather want to write is the following:
list.partitionByType<InterestedType>()
Where InterestedType
is a subtype of the type parameter of the list, i.e. SomeType
. Both solutions above should then give me Pair<List<InterestedType>, List<SomeType>>
as a return value.
This however isn't really possible. The best that comes to my mind is a signature similar as to follows:
inline fun <reified U : Any> Iterable<Any>.partitionByType(): Pair<List<U>, List<Any>>
But then we lose the actual type T
/SomeType
which was known otherwise. An unchecked cast is still possible on the caller side, but that's not what I am after.
So my question is: is this somehow possible? Having something like U : T
in place, without specifying the T
? Or is there anything planned in this regard (KEEP or Kotlin issue available)?
For me it sounds like a reasonable feature, at least as long as it is applied on an extension function only. If it's not, what would be the problems of this that I am probably just overlooking/ignoring at the moment? What I am not really looking for is a workaround (like having an intermediate type), but it may be worth it to have it as answer as well.
The more I think of it. Wouldn't it be more correct, if extension functions on generic types would be declared as follows?
fun SomeType<T>.extended()
instead of
fun <T> SomeType<T>.extended()
Because: if I were under control of SomeType<T>
and would add that function there, I wouldn't need any generic type information to declare it, e.g. the following would suffice then:
fun extended()
Same regarding functions with own generic types, e.g.:
fun <U : T> extended2()
Adding that as extension function now forces one to add that T
-generic type, although the type on which we would like to apply it, is clearly SomeType<T>
:
fun <T, U: T> SomeType<T>.extended2()
inline class
should probably also be applied for myPartitionType
-class... (but what should the parameter be then...KClass<T>
andT: Any
? some other wrapper type just to deliver the generic type? don't know... I will skip it for the moment :-)) – Bailly