Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

276
Views
Why isn't Kotlin complaining about ambiguity? And why is it calling the secondary constructor?

I was testing something in Kotlin and now I won't be able to sleep properly if I don't find an answer.

Look at this class:

data class Person(
    val name: String,
    val age: Int? = 0
) {
    constructor(
        secondName: String,
        secondAge: Int = 5
    ) : this(
        name = "$secondName 2",
        age = secondAge
    )
}

fun main() {
    val firstCase  = Person("Lorem")     // Complaints about ambiguity.
    val secondCase = Person("Lorem", 42) // Calls secondary constructor.
}

Complaining about ambiguity in the firstCase is understandable, but why it is not happening the same in the secondCase? And why did it decide to call the secondary constructor and not the main constructor?

Now if I add another parameter on the main constructor with a default value:

data class Person(
    val name: String,
    val age: Int? = 0,
    val isAdult: Boolean = false
) {
    constructor(
        secondName: String,
        secondAge: Int = 5
    ) : this(
        name = "$secondName 2",
        age = secondAge
    )
}

fun main() {
    val thirdCase = Person("Lorem") // Calls secondary constructor.
}

I was expecting to have ambiguity for the thirdCase, just like in the firstCase. But no! It calls the secondary constructor. Why?!

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

The rules of method resolution in Kotlin (and in Java) can be a bit arcane. Thankfully, they do the obvious thing in nearly all situations — which is clearly the point! — but there are a few surprising corner cases.

The general principle is that it picks the most specific method that could match, and only gives an error if there isn't a single winner.

So in your second case, the arguments are String and Int. The candidates are the primary constructor (taking String and Int?), and the secondary constructor (taking String and Int). The latter is a more specific match, because Int is a subtype of Int?, and so it picks that one.

But in your first case, the only argument provided is a String, which matches both constructors equally, so there's no clear winner, and it flags up the ambiguity.

Your third case is even less obvious. However, the section of the Kotlin spec that discusses how to choose the most specific candidate from all the overloads says:

For each candidate we count the number of default parameters not specified in the call (i.e., the number of parameters for which we use the default value). The candidate with the least number of non-specified default parameters is a more specific candidate

I think that's what's happening in your third case: it picks the secondary constructor (which would leave only one parameter with its default value) over the primary (which would leave two).

over 4 years ago · Santiago Trujillo Report

0

Kotlin gives more priority to a function that is more specific. Consider this example:

foo(dog) // invokes foo(Dog)

fun foo(animal: Animal) {}
fun foo(dog: Dog) {}

In this case foo(dog) is also ambiguous, but in fact, it uses foo(Dog) function. To use the other one, we have to explicitly upcast:

foo(dog as Animal)

Because Int is a subtype of Int?, your secondary constructor is more specific than the primary constructor and this is why it is preferred.

over 4 years ago · Santiago Trujillo Report

0

In your first example, there is no ambiguity when you use two arguments, because it selects the constructor with the most specific type matching your parameter. There is no ambiguity to choose between the one with Int and the one with Int? because Int is more specific than Int?.

When you provide a single argument, it is ambiguous since you are not providing any argument that can help distinguish whether you want Int or Int?.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!