首页 > 解决方案 > 具有默认函数参数值的 Kotlin 接口

问题描述

我想在实现接口的类中为函数参数使用默认值,如下所示:

interface FileStoreService {
    fun storeFile(path: String, payload: InputStream, type: MediaType, replace: Boolean = true)
}
class LocalFileStoreService : FileStoreService {

    override fun storeFile(path: String, payload: InputStream, type: MediaType, replace: Boolean /* ?? */) {
        // ....
    }
}

现在这是编译的,这是不编译的:

KO : 不允许重写函数为其参数指定默认值

class LocalFileStoreService : FileStoreService {

    override fun storeFile(path: String, payload: InputStream, type: MediaType, replace: Boolean = true) {
        // ....
    }
}

KO:“LocalFileStoreService”类不是抽象的,也没有实现抽象成员 public abstract fun storeFile(path: String, payload: InputStream, type: MediaType): Unit defined in fqn...FileStoreService

class LocalFileStoreService : FileStoreService {

    override fun storeFile(path: String, payload: InputStream, type: MediaType, replace: Boolean) {
        // ....
    }
}

好的

class LocalFileStoreService : FileStoreService {

    override fun storeFile(path: String, payload: InputStream, type: MediaType) {
        storeFile(path, payload, type, true)
    }

    override fun storeFile(path: String, payload: InputStream, type: MediaType, replace: Boolean) {
        // ....
    }
}

这是预期的行为吗?有没有更好的方法来管理接口中的默认参数值?

标签: kotlin

解决方案


您所描述的很奇怪,因为通过尝试使用 Kotlin 1.4.20 重现它,我看不到相同的行为。

下面的代码工作正常:

interface Test {
    fun test(p1: String, p2: Boolean = true)
}

class TestImpl : Test {
    // below commented function breaks compilation
    //override fun test(p1: String) = println("That's odd... received: $p1")

    // You cannot overwrite default value, that would break interface contract
    override fun test(p1: String, p2: Boolean) = println("It works ! Received: $p1 and $p2")
}

fun main() {
    // Default value for second parameter is deduced from interface signature 
    TestImpl().test("Hello")
}

如果我取消注释没有布尔参数的函数,编译会崩溃,因为该方法不是从接口继承的。

一般来说,如果您在接口级别定义默认值,那么更改特定实现的默认值将是一个坏主意,因为它会破坏 API 协定。

编辑

请注意,从注释函数中删除 override 关键字将产生有效代码,因为它成为特定于实现的函数。不过,我发现这种行为很危险,因为以下程序:

interface Test {
    fun test(p1: String, p2: Boolean = true)
}

class TestImpl : Test {
    fun test(p1: String) = println("That's odd... received: $p1")
    override fun test(p1: String, p2: Boolean) = println("It works ! Received: $p1 and $p2")
}

fun main() {
    val t : Test = TestImpl()
    t.test("Hello")
    (t as TestImpl).test("Hello")
}

然后将产生这个输出:

It works ! Received: Hello and true
That's odd... received: Hello

推荐阅读