Reputation: 27
could anyone explain to me the syntax of this interface implementation? Why I need to use the sign '=' to implement CommandLineRunner. When I use sign ':'(accord to basic syntax http://kotlinlang.org/docs/reference/interfaces.html) compiler requires a return statement.
@SpringBootApplication
class Application{
@Bean
fun imageProcess(repo: MongoRepository) = CommandLineRunner {
val room2 = Room(id ="1AN1",
primaryUnit = "XYZ")
repo.save(room)}}
@FunctionalInterface
public interface CommandLineRunner {
void run(String... args) throws Exception;}
Upvotes: 1
Views: 3981
Reputation: 4853
Well, assuming this compiles (which isn't clear because you are missing the body of the function), then the following is true:
imageProcess
returns a CommandLineRunner
. You can ommit the braces around the function block and simply use an expression bodied function like you have here.
An expression bodied function is one whose body is an expression (where an expression is a block of code that resolves to a value of a specific type).
https://kotlinlang.org/docs/reference/lambdas.html
Take these as examples:
// 1 + 2 + 3 is an expression that resolves to an Integer value.
// Therefore, the return type is Int
fun intExpression() = 1 + 2 + 3
// false && true is an expression that resolves to a Boolean value.
// Therefore, the return type is Boolean
fun boolExpression() = false && true
// The when here is a fully exhaustive when expression
// It can resolve to an Integer or a String.
// Therefore the return type is the common subtype of both
// Integer and String which happens to be Any (the root of the Kotlin type heirarchy.
fun anyExpression(foo: Boolean) = when(foo) {
true -> 1
else -> "Hello"
}
More formal definition of an expression:
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-statement-vs-expression-e6743ba1aaa0
EDIT 1:
To clarify further, what is actually happening is that you are creating an anonymous implementation of the CommandLineRunner
interface. This can only be written in the way you have written it due to the fact the interface defines a single abstract method. This means your CommandLineRunner
interface is a SAM type and the compiler is performing SAM type conversion. In other words, you could have written your code like this:
class MyCommandLineRunner(repo: MongoRepository) : CommandLineRunner {
override fun run(args: String) {
// Do stuff...
}
}
fun imageProcess(repo: MongoRepository) = MyCommandLineRunner(repo)
But, you don't need to do that, because the interface has a single abstract method so you can simply define an inline implementation of the interface without having to explicitly override the run
function.
Read about SAM types and SAM conversion here:
https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
EDIT 2:
Finally, look here:
https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/CommandLineRunner.html
That is the interface you are implementing. As you can see, it does conform to the definition of a SAM type which is why you can create inline implementation of it without explicitly stating the override of the run
function. If the interface had an extra method (let's say stop
) then you would have to write your anonymous implementation like so:
@Bean
fun imageProcess(repo: MongoRepository) = object : CommandLineRunner {
override fun run(args: String) {
// Do stuff
}
override fun stop() {
// Do stuff
}
}
Upvotes: 1