Override named parameters with specific naming

I have a method such as

interface List<T> {
    add(item: T)
}

and I have a subclass such as

class CatsList() : List<Cat> {
    add(cat: Cat)
}

The compiler argues with warning that overriding item named argument with cat may cause problems if someone wishes to do: catList.add(item = meowth)

I believe it sometimes makes sense to change the named argument to a more specific name for your derived class. It would be nice to have an option to explicitly rename the args.

1 Like

Here’s a runnable example:

//sampleStart
open class Box {
    open fun put(item: Any) {}
}

class CatBox : Box() {
    // @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
    override fun put(cat: Any) {}
}
//sampleEnd

fun main() {
    println("Hover over the ! icon to read warning")
}

I would suggest it is rare to name an argument with a more specific name without weakening your code. The meaning behind the argument’s name should likely be the same as the parent since it should be substitutable (LSP)

With that said, you do have the option to do this. It is only a warning and your code will compile. You can use Kotlin’s Suppress to drop the warning.

Try uncommenting the @suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") in the example above. The suppress can be on the method (like in the example), the class, or the file

@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
fun foo() { /* only this method suppressed */ }

@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
class Foo { /* the entire class suppressed */ }

@file:Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
/* everything in the file suppressed */
1 Like

I believe that this doesn’t really address the question. Having to suppress warning in each and every implementation is a nuisance; besides, it indeed breaks LSP.

However, what if we restrict the usage on the interface level instead? Suppose we have a generic interface, like a codec, which is implemented far more frequently than used. The function will only have one parameter, so it doesn’t make sense to use named parameter there. However, it makes much more sense to use domain-specific name in the implementation.

I would propose an opt-out of calling by name: an annotation that prohibits calling by name, only by position. What do you think?

True, suppressing the name change doesn’t address the request to give a new label when calling the function with named parameters.

I can the compiler accepting param names for whichever specific type the compiler knows and also supporting the labels from super types.

Although now I must admit I don’t know how Kotlin handles this now. I’d also wonder if other languages like Swift handle this issue with overriding functions and changing labels.

1 Like