I run into a situation that seems Kotlin allows sub-class create the same signature as super-class’s getter.
Generally, functions has same signature and different return type is not allowed. So I’m confused about this situation. I’m not sure whether this is by designed.
Here is a sample:
open class BaseRequest {
val params = mutableMapOf<String, String>()
init {
params["key1"] = "value1"
}
}
class SpecificRequest : BaseRequest() {
init {
params["key2"] = "value2"
}
fun getParams(): List<String> {
return params.values.toList()
}
}
MediatorRequest has a function getParams()
which has same signature as it’s super-class but has different return type. While using this function, it seems the sub class and super class has different implement of the same declaration.
fun main() {
val specificRequest = SpecificRequest()
println("specificRequest.params: ${specificRequest.params}")
println("specificRequest.getParams(): ${specificRequest.getParams()}")
println("(specificRequest as BaseRequest).params: ${(specificRequest as BaseRequest).params}")
}
The Output would be like this:
specificRequest.params: {key1=value1, key2=value2}
specificRequest.getParams(): [value1, value2]
(specificRequest as BaseRequest).params: {key1=value1, key2=value2}
If we look at the decompiled Java code, there are two methods has same signature and different return type and this is truly not allowed in Java.
public class BaseRequest {
@NotNull
private final Map params;
@NotNull
public final Map getParams() {
return this.params;
}
/* ... */
}
public final class SpecificRequest extends BaseRequest {
@NotNull
public final List getParams() {
return CollectionsKt.toList((Iterable)this.getParams().values());
}
/* ... */
}
I know the function name is not appropriate but there is a potential risk that if we use the SpecificRequest
in .java, we can not visite the Map params until we cast the instance to it’s super class. And this may lead to misunderstanding.