class Main {
fun main(args: Array<String>) {
val a = DefaultTest()
a.test("1", "1")
}
}
class DefaultTest {
fun test(a: String, b: String?) {
println("test1")
}
fun test(a: String, b: String, c: String = "c") {
println("test2")
}
}
When I run the class, the result is “test2”. Actually, I was expected “test1”.
So, I run this code after changing b: String? to b: String of the first test function.
The result was “test1”.
I was wondering that how compiler pick a function to run.
I think it might be overload ambiguity.
@fatjoe79 Thank you for the reply. I think it has not the same reason.
It depends on nullability and parameter (defined in Kotlin compiler) not the different type like String and Any.
Is there any way to run String? parameter function?
fun test(s: String) = print("test1")
fun test(s: Any) = print("test2")
val string : String? = "test"
a.test(string) //type mismatch error
Also, below code doesn’t compile by that the same JVM signuare test (Ljava/lang/String;)V
fun test(s: String) = print("test1")
fun test(s: String?) = print("test2")
The result goes to “test2” with explicit casting String?.
It’s ok in Kotlin perspective. But it’s not in Java perspective.
In Java perspective, there is no need to cast to run fun test(a: String, b: String?).
//Java
DefaultTest a = new DefaultTest();
a.test("1","1"); //"test1"
//Kotlin
val a = DefaultTest()
a.test("1", "1" as String?) //"test1"
a.test("1", "1") //"test2"
So, I’m looking for language specification about that. Is this “undefined behavior” or not?
For better Java Interoperability and safety, it might be overload ambiguity or something like warning.
It’s possibility to run unexpected behavior by the overload functions.
In Kotlin String is a more specific type than String?.
In Java does the statement String.valueOf("hello") invoke String.valueOf(String) or String.valueOf(Object)? It invoke the more specific type.
In your Java experiments you can replace Object for String?.
I thought String is the same type as String? except nullability.
So, I was wondering how Kotlin compiler resolves function overloading by what kind of criteria.
For this case, Kotlin compiler picks a more specific type method. (“test2”)
I also would like more documentation about overload resolution. Say we have
fun test(a: Any) = TODO()
fun test(a: String, b: String = "Hello") = TODO()
fun test(vararg a: String) = TODO()
does calling test("Hello") call the first method with the right number of parameters, but a less specific type, the second version with the right type but the unneeded second parameter, or the third version with a varargs parameter and the right type?
Sure, you could just try it, but it should be formally documented somewhere. I haven’t found such documentation, yet.
I think that two of the predetermined speakers have right at least regarding missing explanation in documentation.
In my humble developer opinion (not as language creator) this is inconsistent behaviour, which stays against what Kotlin’s team is officially presenting in their “Kotlin Type System Hierarchy”, where difference between null and not null types is explicitly marked.
It’s inconsistent because if want to run
class MyClass
fun notNull(name: MyClass){}
main(){
val myClass : MyClass ?= null
notNull(myClass)
}
compailer will complain Type mismatch inferred type is MyClass? but MyClass was expected
Of course MyClass is not a String. But in other hand they both ihnerit from Any, which should mean that they both behave the same