Search code examples
kotlinjvmsingle-abstract-method

Single abstract member cannot declare default values


I am following SonarLint recommendation to convert some interface that only have one function to SAM, but got issue due to having default value in the function parameter.

fun interface HomeListener {

   fun setSubTitle(subtitle: String = DEFAULT_VALUE_STRING)

}

I want to know what is the problem here or is this a limitation between Kotlin and JVM? There is already a bug report of this in JetBrain's issue tracker but has no update since 2021?


Solution

  • As my understanding goes, the point of SAM is that if there is only one abstract method to be implemented you could just provide a lambda letting the compiler use it as the implementation. Normally it is you requesting the object with the implementation whereas the "user" needs to provide it, with the option to doing so by providing only a lambda. This would correspond to a direct lambda parameter:

    fun doStuff(onSubtitleChange: (String) -> Unit) {
        ...
        onSubtitleChange("foo")
        ...
    }
    

    Meaning that setSubTitle in your case is not meant to be called by the "user" but by you so it doesn't need an outwards interface. Just like with the lambda paramter you wouldn't do this (which is wrong syntax of course):

    fun doStuff(onSubtitleChange: (String = DEFAULT_VALUE_STRING) -> Unit) {
        ...
        if (processedString != null)
            onSubtitleChange(processedString)
        else
            onSubtitleChange()
        ...
    }
    

    But you would do this which is just clearer and makes more sense:

    fun doStuff(onSubtitleChange: (String) -> Unit) {
        ...
        onSubtitleChange(processedString ?: DEFAULT_VALUE_STRING)
        ...
    }
    

    So as it seems to me there is just no point in having a default argument. Rather provide it like so:

    fun doStuff(listener: HomeListener) {
        ...
        listener.setSubtitle(processedString ?: DEFAULT_VALUE_STRING)
        ...
    }