Reputation: 2567
When writing a function in Kotlin, that is basically fully implemented inside of a Thread
creation and it's start()
, Android Studio gives the option to "Convert to expression body"
When choosing to do so, kotlin converts the function to an expression body:
Is there a way to demand this for an interface (like the one this function is overriding)?
I want the interface to always require the validate
function to start a new Thread
and only (!!) be able to execute the things inside of that Thread
, not in the method body itself, because it will only be used to address the server.
I know I could force that behavior, by using an abstract class
instead of an interface
like this:
abstract class ServerValidator<T> {
fun validate(value: T?, function: ((ValidationResult) -> Unit)) = Thread {
doValidation(value, function)
}.start()
protected abstract fun doValidation(value: T?, function: ((ValidationResult) -> Unit))
}
So that an inheriting class would be able to override the doValidation
function while another class would only be able to call validate
and thereby always use a new thread.
However, I'd specifically like to know whether it's possible to do something like this with an interface.
Something like:
interface ServerValidator<T> {
fun validate(value: T?, function: ((ValidationResult) -> Unit)) = Thread::start
}
// or
interface ServerValidator<T> {
fun validate(value: T?, function: ((ValidationResult) -> Unit)) : Thread::start
}
Upvotes: 0
Views: 784
Reputation: 19562
An expression body is just another way of writing the function block, as a single expression instead of using braces with a return. It can be neater and more expressive (especially since you can omit the return type).
Arguably you should only use expression bodies for expressions that return something other than Unit (i.e. they return a value instead just having side effects), but there's nothing enforcing that.
Your question about the interface is a whole other thing, as far as I know there's no way to force a function implementation to include a particular behaviour. I think it would probably be better to have your interface function define the validation process (or return a function you can run to perform that validation), and dispatch that to something else that will actually run it (and that's where you can control if it uses worker threads, a thread pool, coroutines etc)
Upvotes: 3
Reputation: 93779
Expression body has nothing to do with function signature. It's purely a syntax alternative. In both cases with your example, the function is returning Unit
because in the expression body case, it is returning what Thread.start()
returns, which is Unit
.
What I think you're actually asking is whether you can define not only what a function returns, but an intermediate step in how it gets to that result, i.e. forcing it to do something on a background thread. And the answer is no. There exists nothing in the language for defining a construct like that.
You've already described the correct way to do it, which is to take a function parameter, and then the receiving class can call it in a background thread on its own.
A different approach might be to define the function as a suspend
function, which means it should not perform blocking code without using an appropriate coroutine Dispatcher for blocking code. Then if the person implementing the interface function fails to use a background Dispatcher, they are breaking the contract of how suspend
functions are supposed to work. But the compiler still won't force them to do it correctly.
Upvotes: 5