【问题标题】:Implementing interfaces in Kotlin在 Kotlin 中实现接口
【发布时间】:2018-10-18 10:06:41
【问题描述】:

谁能给我解释一下这个接口实现的语法? 为什么我需要使用符号 '=' 来实现 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;}

【问题讨论】:

    标签: kotlin interface implementation


    【解决方案1】:

    好吧,假设这个编译(不清楚,因为你缺少函数的主体),那么以下是正确的:

    imageProcess 返回一个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
       }
    }
    

    【讨论】:

    • 为什么不编辑原始问题以显示函数体而不是将其粘贴在评论中?
    • 我有点迷茫,我不知道这里的一切如何。我编辑了我的帖子,希望现在更清楚。
    • 所以不是接口实现,而是lambda?
    • 不,您正在实现 CommandLineRunner 接口,请参阅我即将进行的编辑。
    猜你喜欢
    • 1970-01-01
    • 2018-06-25
    • 1970-01-01
    • 2020-10-17
    • 2021-01-29
    • 2019-10-03
    • 2017-12-30
    • 2017-10-23
    • 2019-07-09
    相关资源
    最近更新 更多