代码之家  ›  专栏  ›  技术社区  ›  Mosius sMiLo

如何重载具有相同参数类型但其中一个可为null的函数

  •  5
  • Mosius sMiLo  · 技术社区  · 6 年前

    我在尝试给它添加两个扩展函数 Calendar 类将特定的日期时间模式转换为日历,反之亦然

    fun Calendar.fromIsoString(date: String): Calendar = this.apply {
        time = SimpleDateFormat(SERVER_DATE_PATTERN, Locale.US).parse(date)
    }
    
    fun Calendar.fromIsoString(date: String?): Calendar? {
        if (date == null) return null
        time = SimpleDateFormat(SERVER_DATE_PATTERN, Locale.US).parse(date)
        return this
    }
    

    但它给了我以下错误:

    平台声明冲突:以下声明具有相同的JVM签名(fromIsoString(Ljava/util/Calendar;Ljava/lang/String;)Ljava/util/Calendar;)

    这两种功能是否可以同时使用?怎样

    注: 我通过添加一个 Unit 其中一个函数的可选参数:

    fun Calendar.fromIsoString(date: String?, a: Unit = Unit): Calendar? {
    if (date == null) return null
        time = SimpleDateFormat(SERVER_DATE_PATTERN, Locale.US).parse(date)
        return this
    }
    

    但我认为这很棘手,不是一个好的做法! 有更好的解决办法吗?

    1 回复  |  直到 5 年前
        1
  •  5
  •   Jayson Minard    6 年前

    有一个简单的解决方案,允许您在不更改方法或希望从Kotlin调用它们的名称的情况下执行此操作。

    对于Kotlin来说,这两种方法之间的区别是明确的,但对于JVM来说则不然。因此,只需告诉Kotlin,您希望其中一个方法使用不同的内部JVM名称,这根本不会影响Kotlin代码。只有Java代码才能看到替代名称。例如:

    fun Calendar.fromIsoString(date: String): Calendar = this.apply {
        // ... your code without change
    }
    
    @JvmName("fromIsoStringNullable") // <-- this solves your problem without changing the name in Kotlin
    fun Calendar.fromIsoString(date: String?): Calendar? {
        // ... your code without change
    }
    

    瞧!别再犯错误了!您可以使用相同的名称从Kotlin调用任一版本 someCalendar.fromIsoString(...)

    其他的答案和评论表明,可空性是句法上的糖分,但这些答案和评论远远不正确。这些类型作为额外的元数据写入字节码,只有Kotlin才能看到并执行这些元数据。但除此之外,它还增加了 @Nullable 参数的注释。事实上,所有Kotlin生成的函数参数 @NotNull @可为空 字节码中的注释,以供其他语言或分析器查看和执行,如果他们足够关心的话。