Kotlin中接口的Lambda实现

35

那段代码在 Kotlin 中应该怎么写?我尝试了很多方法,但好像都不行:

public interface AnInterface {
    void doSmth(MyClass inst, int num);
}

初始化:

AnInterface impl = (inst, num) -> {
    //...
}

对于未来的读者,你可能还想看一下https://stackoverflow.com/a/58725404/48136。 - undefined
5个回答

37

如果AnInterface是Java,那么您可以使用SAM转换来处理:

val impl = AnInterface { inst, num -> 
     //...
}

否则,如果接口是Kotlin ...

interface AnInterface {
     fun doSmth(inst: MyClass, num: Int)
}

...你可以使用object语法来匿名实现它:

val impl = object : AnInterface {
    override fun doSmth(inst:, num: Int) {
        //...
    }
}

3
为什么Kotlin接口没有类似Java的SAM转换?是否有任何方法可以将“AnInterface {inst,num->}”应用于Kotlin接口? - abitcode
你可以在这里点赞支持这个问题: https://discuss.kotlinlang.org/t/sam-conversion-on-kotlin-interfaces/1433 - Re'em
如果我想将它传递给一个以AnInterface为参数的函数,我该怎么写呢?是这样吗? myFun(object : AnInterface { override fun doSmth(ints:, num: Int) { ... } }) 肯定有更好的方法! - MiguelMunoz

22

如果你正在将接口和其实现都重写为Kotlin,那么你应该删除接口并使用函数类型:

val impl: (MyClass, Int) -> Unit = { inst, num -> ... }

这是正确的答案...其他两个答案没有涉及到lambda实现。但是,如果我仍然想要使用自己声明的接口(出于可读性的原因),这是否意味着我不能使用lambda? - Sira Lam
1
@SiraLam 你可以为函数类型声明一个默认变量名:val listener: (name: Class, other: OtherClass) -> Unit - TheWanderer
2
@SiraLam 如果你因为可读性的原因想要接口,那么你可能正在遭受原始偏执症。简而言之,不要将原始类型用作参数。这个签名的函数 (String) -> String 做什么?没有名称,你无法理解它。现在,这个签名的函数 (UserId) -> PhoneNumber 做什么?嗯,唯一合理的实现方式是通过ID查找用户数据,然后提取电话号码并返回它。如果你的函数不使用原始类型,则通常不需要将它们包装在接口中以提高可读性。 - Matt Klein

4

您可以使用对象表达式

这样看起来就像这样:

val impl = object : AnInterface {
    override fun(doSmth: Any, num: Int) {
        TODO()
    }
}

1

谢谢,这应该是被选中的答案。 - Péter Veres

1

您还可以像这样做,使用@lambda标签


interface AnInterface {
     fun doSmth(inst: MyClass, num: Int)
}

val impl = AnInterface lambda@{inst, num ->
    //..
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接