https://kotlinlang.org logo
#coroutines
Title
# coroutines
c

chanjungskim

01/19/2023, 9:34 AM
How can I make interface functions to suspend function? for example,
Copy code
interface BaseClass{
    fun foo()
    fun bar()
}
Copy code
class ChildClass: BaseClass {
    override fun foo()
    override fun bar()
}
My expectation is,
Copy code
class ChildClass: BaseClass {
    override suspend fun foo()
    override suspend fun bar()
}
Is that possible?
h

hfhbd

01/19/2023, 9:43 AM
Copy code
interface BaseClass{
    suspend fun foo()
    suspend fun bar()
}
c

chanjungskim

01/19/2023, 9:50 AM
then every child class will override suspend fun funtions.
h

hfhbd

01/19/2023, 9:56 AM
Yes. You can't override a non-suspend function with a suspend function and vice-versa.
c

CLOVIS

01/19/2023, 9:59 AM
You cannot call
suspend
functions from regular functions. Imagine if you could do what you wanted:
Copy code
fun main() { // non-suspend main
    val a: BaseClass = ChildClass()

    // we're calling the 'a' function of the base class, which is not suspend, that's OK
    a.foo()
}
What would happen? It can't call the overriden function, because it's
suspend
and we're in a function where
suspend
is not allowed.
j

Joffrey

01/19/2023, 2:44 PM
To put it more plainly, a
suspend
function technically has a different signature (in bytecode), so it's not a valid override for a non-suspend function
then every child class will override suspend fun funtions
@chanjungskim What is the problem with this?
c

CLOVIS

01/19/2023, 2:45 PM
@Joffrey that's true, but it makes it seem like it's a technical limitation of coroutines, whereas it's on purpose because it wouldn't make sense even if it was possible to make it compatible in bytecode
j

Joffrey

01/19/2023, 2:46 PM
Right. It was not my intention to convey that idea, so you're right that it might not be the best angle to explain this 😅
A more correct explanation is that a
suspend
function has a different contract from a regular function
c

CLOVIS

01/19/2023, 2:47 PM
(more generally, this concept of "contract" is called "code coloring", if anyone is interested by the broader theory)
k

krzysztof

01/19/2023, 3:47 PM
c

chanjungskim

01/19/2023, 6:43 PM
Well, still I don't understand why it's not possible. I am actually implementing logger with Slack webhook and Datadog. I wanted to create a common parent class for making them interchangeable. Datadog uses async call under the hood. But my custom webhook doesn't. using suspend function has no problem with calling normal function like Datadog but, that can be confusing if Datadog use supend function because it doesn't need suspend actually.
c

Casey Brooks

01/19/2023, 7:00 PM
It’s not usually confusing to override a
suspend
function and then never suspend within it, any more than overriding a function and ignoring parameters passed to it that you don’t need. But it communicates that the code is intended to run async, may be running on background threads rather than the main thread, and helps with handling errors thrown within it. So even if you’re not strictly calling any
suspend
functions within the Datadog implementation, there is still usefulness to having the method marked suspend
c

CLOVIS

01/19/2023, 7:02 PM
suspend
functions are colored differently than regular functions, they can never be compatible. You want to create a common ancestor, but synchronous and asynchronous are very different things.
u

uli

01/20/2023, 2:41 PM
@Casey Brooks even though it is fine for a suspend function not to suspend, it is not ok to block in a suspend function. The implicit contract of a suspend function is to not block the current thread but to suspend (and potentially schedule to another thread for blocking)
j

Joffrey

01/20/2023, 2:43 PM
@uli true, but that is not very confusing for implementers of the interface with
suspend
methods. Technically they are aware of the
suspend
keyword and should implement the function accordingly (at least with some
withContext()
to dispatch to another thread)
455 Views