I have a situation in which I am attempting to inherit the generic type of an abstract class to its internal interface.
For example:
MyAbstractClass.kt
abstract class MyAbstractClass<T> {
fun interface MyInterface {
suspend fun doSomething(param: T)
}
private var _callback: MyInterface? = null
fun someFunction(callback: MyInterface?) {
(...)
}
(...)
}
Unfortunately the above does not work, and I believe it is because despite the interface being inside an abstract class does not necessarily mean it is an instance of it, but its own file which happens to be located inside that class.
I understand I could just do the following:
MyInterface.kt
fun interface MyInterface<T> {
suspend fun doSomething(param: T)
}
And problem would be solved, but that would not work for my purpose because then it would have to be used like this:
// the type is only implicit in the lambda because it was made explicit in the function
myAbstractClassInstance.someFunction<ExplicitTypeHere> { it: ExplicitTypeHere ->
(...)
}
Whereas I want to have the type inherited so functions like the above can be written like this:
// the type is implicit in the lambda now without having to specify it beforehand
myAbstractClassInstance.someFunction { it: ExplicitTypeHere ->
(...)
}
I came up with a way to achieve what I want - but I would really prefer to use an interface for this since it would be cleaner and easier to update. This is what I have that does what I want:
MyAbstractClass.kt
abstract class MyAbstractClass<T> {
private var _callback: (suspend (param: T) -> Unit)? = null
fun someFunction(callback: (suspend (param: T) -> Unit)?) {
(...)
}
(...)
}
But again, I would prefer a lot more if I could achieve the same via an interface without having to specify the type. How can I accomplish that?
Here’s how you can implement your original attempt to work. If we are invoking the passed interface in someFunction
, then someFunction
has to be abstract because in practice we don't know what T
is in the abstract class.
abstract class MyAbstractClass<T> {
fun interface MyInterface<T> {
suspend fun doSomething(param: T)
}
private var _callback: MyInterface<T>? = null
abstract fun someFunction(callback: MyInterface<T>?)
}
fun main() {
val x = object: MyAbstractClass<String>() {
override fun someFunction(callback: MyInterface<String>?) {
runBlocking { callback?.doSomething("Hello world") }
}
}
x.someFunction {
println(it)
}
}