如何创建接口的匿名实现?

gvl*_*sov 45 interface kotlin

我有一个界面:

interface TileSet {
    fun contains(x: Int, y: Int) : Boolean
}
Run Code Online (Sandbox Code Playgroud)

我希望能够创建多组瓷砖(瓷砖是一对x和y整数坐标):

fun TileSet.union(another: TileSet) : TileSet = 
   // ..
Run Code Online (Sandbox Code Playgroud)

在Java 8中,我可以这样做:

@FunctionalInterface
public interface TileSet {
    boolean contains(int x, int y);

    public default TileSet unite(TileSet another) {
        return (x, y) -> TileSet.this.contains(x, y) && another.contains(x, y);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以接口是用lambda实现的TileSet#unite().或者它可以用旧的匿名类方法实现:

public default TileSet unite(TileSet another) {
    return new TileSet() {
         @Override
         public boolean contains(int x, int y) {
             return TileSet.this.contains(x, y) && another.contains(x, y);
         }
    }
}
Run Code Online (Sandbox Code Playgroud)

如何在Kotlin中创建单方法接口的匿名实现?

如果我使用(Int, Int) -> Boolean而不是,我知道该怎么做TileSet,但我希望该类型具有描述性名称而不仅仅是函数签名.

gvl*_*sov 67

匿名类的文档中有一些示例,但接口没有.

这是我创建接口实例的方式:

fun TileSet.union(another: TileSet) : TileSet =
    object : TileSet {
        override fun contains(x: Int, y: Int) : Boolean =
            this@union.contains(x, y) || another.contains(x, y)
    }
Run Code Online (Sandbox Code Playgroud)

请注意,与文档中的示例不同,之后没有括号object : TileSet.

  • @danielgomezrico那一定是因为你的基类/接口(在我的例子中是`TileSet`)声明了一个抽象方法,你应该在你的匿名实现中实现它. (2认同)

Fer*_*nch 6

我进行了一些试验,惊讶地发现您可以使用 Kotlin lambdas实现Java函数式接口:

// Implementing Java functional interfaces using lambdas
val greeter = Consumer<String> { println("Hi $it") }
val dice = Supplier { ThreadLocalRandom.current().nextInt(1, 7) }
Run Code Online (Sandbox Code Playgroud)

但是当你实现Kotlin函数式接口时,你需要完整的仪式

// Implementing a Kotlin functional inteface with lambdas is not possible
val greeter = object : MyConsumer<String> {
    override fun accept(x: String) {
        println("Hi $x")
    }
}

@FunctionalInterface
interface MyConsumer<T> {
    fun accept(x:T)
}
Run Code Online (Sandbox Code Playgroud)

我想知道为什么在从 Kotlin 实现 Kotlin 接口时需要完整的匿名类语法!

也许他们希望你改用函数?可以这样做。

// If you want to use lambdas, define a function instead of an interface
val greeter: MyConsumerFunction<String> = { println("Hi $it") }

typealias MyConsumerFunction<T> = (T) -> Unit
Run Code Online (Sandbox Code Playgroud)

无论如何,如果有人对此有所了解,请告诉我!:)

  • 是的,每次遇到这种事我都会很生气。我知道常规函数更惯用,但是当您处理依赖注入框架(例如旧版本的 Guice 和 Spring)时,它们不能与 Kotlin 函数一起使用,那么声明接口总体上更容易,除非涉及到创建这些接口。有时我只是在 Java 文件中创建接口,这样我就可以避免 Kotlin 仪式...... (2认同)