Kotlin:为什么用附加的可选参数覆盖不起作用?

unhi4e5o  于 2022-12-04  发布在  Kotlin
关注(0)|答案(1)|浏览(118)

我试图用一个具有可选参数的自定义toString来覆盖数据类的toString函数,但它没有按预期工作:

data class LatLong(
    val latitude: Double,
    val longitude: Double
    ){
    
    // Override keyword not allowed by compiler here
    fun toString(decimals: Int = 5) =
        "${"%.${decimals}f".format(latitude)}, ${"%.${decimals}f".format(longitude)}"
}

fun main() {
    println(LatLong(-123.0, 49.0))  // prints: "LatLong(latitude=-123.0, longitude=49.0)"  i.e. does not call custom toString
    println(LatLong(-123.0, 49.0).toString())  // prints: "LatLong(latitude=-123.0, longitude=49.0)"  i.e. does not call custom toString
    println(LatLong(-123.0, 49.0).toString(decimals=5))  // prints: "-123.00000, 49.00000"
}

问题是,我应该如何覆盖它,以获得您所期望的行为(即,上面的所有3个调用都应该使用自定义方法)?
我当然可以加上

override fun toString() = toString(decimals=5)

但这意味着要定义两次default参数,这会导致将来的bug。当然,我可以将default定义为常量和toString a的引用,但这看起来很混乱。令人惊讶的是LatLong(...).toString()没有调用新方法。

什么是“Kotlinic”方式来处理这个问题?

1tu0hz3e

1tu0hz3e1#

你不需要声明两次默认值,只需在toString覆盖中声明它,而不是在你自己的toString参数列表中声明:

override fun toString() = toString(decimals = 5)

// make this a required parameter
fun toString(decimals: Int) =
    "${"%.${decimals}f".format(latitude)}, ${"%.${decimals}f".format(longitude)}"

当然,如果您有更多的格式选项,这会变得有点复杂,但您总是可以将所有内容 Package 在一个(数据)类中,并以一个参数结束。

data class FormatOptions(
    val decimals: Int = 5,
    val someOtherOption: Int = 10
)

override fun toString() = toString(FormatOptions(/* ... */))

fun toString(options: FormatOptions): String = TODO()

顺便说一下,调用toString()的参数列表 * 完全 * 匹配数据类自动声明的无参数toString重载。另一方面,如果考虑可选参数,它只匹配您声明的重载。因此编译器有很好的理由更倾向于将LatLong(...).toString()解析为无参数toString方法,而不是您声明的方法。

相关问题