在 Kotlin 中实现接口
Implementing interfaces in Kotlin
谁能给我解释一下这个接口实现的语法?
为什么我需要使用符号 '=' 来实现 CommandLineRunner。当我使用符号 ':'(根据基本语法 http://kotlinlang.org/docs/reference/interfaces.html)时,编译器需要一个 return 语句。
@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;}
好吧,假设编译成功(这还不清楚,因为您缺少函数的主体),那么以下内容为真:
imageProcess
returns一个CommandLineRunner
。您可以省略函数块周围的大括号,并像此处一样简单地使用表达式主体函数。
表达式主体函数是主体是表达式的函数(其中表达式是解析为特定类型值的代码块)。
https://kotlinlang.org/docs/reference/lambdas.html
以这些为例:
// 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"
}
表达式的更正式定义:
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-statement-vs-expression-e6743ba1aaa0
编辑 1:
为了进一步澄清,实际发生的是您正在创建 CommandLineRunner
接口的匿名实现。由于接口定义了一个抽象方法,因此只能按照您编写的方式编写。这意味着您的 CommandLineRunner
接口是 SAM 类型,并且编译器正在执行 SAM 类型转换。换句话说,您可以这样编写代码:
class MyCommandLineRunner(repo: MongoRepository) : CommandLineRunner {
override fun run(args: String) {
// Do stuff...
}
}
fun imageProcess(repo: MongoRepository) = MyCommandLineRunner(repo)
但是,您不需要这样做,因为接口只有一个抽象方法,所以您可以简单地定义接口的内联实现,而不必显式覆盖 run
函数。
在此处阅读有关 SAM 类型和 SAM 转换的信息:
https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
编辑 2:
最后,看这里:
https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/CommandLineRunner.html
这就是您正在实现的接口。如您所见,它确实符合 SAM 类型的定义,这就是为什么您可以创建它的内联实现而无需明确声明 run
函数的覆盖。如果接口有一个额外的方法(比方说 stop
),那么你将不得不像这样编写你的匿名实现:
@Bean
fun imageProcess(repo: MongoRepository) = object : CommandLineRunner {
override fun run(args: String) {
// Do stuff
}
override fun stop() {
// Do stuff
}
}
谁能给我解释一下这个接口实现的语法? 为什么我需要使用符号 '=' 来实现 CommandLineRunner。当我使用符号 ':'(根据基本语法 http://kotlinlang.org/docs/reference/interfaces.html)时,编译器需要一个 return 语句。
@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;}
好吧,假设编译成功(这还不清楚,因为您缺少函数的主体),那么以下内容为真:
imageProcess
returns一个CommandLineRunner
。您可以省略函数块周围的大括号,并像此处一样简单地使用表达式主体函数。
表达式主体函数是主体是表达式的函数(其中表达式是解析为特定类型值的代码块)。
https://kotlinlang.org/docs/reference/lambdas.html
以这些为例:
// 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"
}
表达式的更正式定义:
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-statement-vs-expression-e6743ba1aaa0
编辑 1:
为了进一步澄清,实际发生的是您正在创建 CommandLineRunner
接口的匿名实现。由于接口定义了一个抽象方法,因此只能按照您编写的方式编写。这意味着您的 CommandLineRunner
接口是 SAM 类型,并且编译器正在执行 SAM 类型转换。换句话说,您可以这样编写代码:
class MyCommandLineRunner(repo: MongoRepository) : CommandLineRunner {
override fun run(args: String) {
// Do stuff...
}
}
fun imageProcess(repo: MongoRepository) = MyCommandLineRunner(repo)
但是,您不需要这样做,因为接口只有一个抽象方法,所以您可以简单地定义接口的内联实现,而不必显式覆盖 run
函数。
在此处阅读有关 SAM 类型和 SAM 转换的信息:
https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
编辑 2:
最后,看这里:
https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/CommandLineRunner.html
这就是您正在实现的接口。如您所见,它确实符合 SAM 类型的定义,这就是为什么您可以创建它的内联实现而无需明确声明 run
函数的覆盖。如果接口有一个额外的方法(比方说 stop
),那么你将不得不像这样编写你的匿名实现:
@Bean
fun imageProcess(repo: MongoRepository) = object : CommandLineRunner {
override fun run(args: String) {
// Do stuff
}
override fun stop() {
// Do stuff
}
}