Reputation: 3362
I'm doing the Kotlin Koans tests in order to familiarise myself with Kotlin. In a certain test I have to override the compareTo
method. In the first case everything work as intended
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) {
operator fun compareTo(other: MyDate)= when {
year != other.year -> year - other.year
month != other.month -> month - other.month
else -> dayOfMonth - other.dayOfMonth
}
}
Now in the second case where I'm writing the compareTo
a little bit differently I get a ton of compilation errors.
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) {
operator fun compareTo(other: MyDate){
when {
year != other.year -> return year - other.year
month != other.month -> return month - other.month
else -> return dayOfMonth - other.dayOfMonth
}
}
}
First of all, at the operator keyword, I get an error:
'operator' modifier is inapplicable on this function: must return Int
and in the returns I get
Type mismatch: inferred type is Int but Unit was expected
I cannot understand why these errors occur since the first implementation returns the same Int
s
Upvotes: 1
Views: 2240
Reputation: 12177
Just an addition to @Mibac's answer: You can make this a little bit shorter:
operator fun compareTo(other: MyDate) = when {
year != other.year -> year - other.year
month != other.month -> month - other.month
else -> dayOfMonth - other.dayOfMonth
}
Upvotes: 0
Reputation: 9488
That's because =
works as { return X }
This applies only to function definitions. So this means that in the first example your code is equal to this
operator fun compareTo(other: MyDate):Int {
return when {
year != other.year -> year - other.year
month != other.month -> month - other.month
else -> dayOfMonth - other.dayOfMonth
}
}
But in your 2nd example you don't return the result of the when
. That results in the compiler being confused because it expected you to return a Int
but you return Unit
instead (equivalent of Java's void
)
So all you need to do is to add an explicit return type (Int
in this case) to it (fun X(/*args*/)
: Int
or other applicable type)
Upvotes: 3
Reputation: 6992
In your first example, the return type of compareTo(MyDate)
is inferred as Int
because all branch of the when
expression return an Int
.
In your second example, the return type of compareTo(MyDate)
is Unit
. Since you function has the block body, so the return type must be specified explicitly (unless it's intended for them to return Unit
). So, Unit
is expected here for the return type, but the return type inferred from your when
expression is Int
. That's why you get the error:
Type mismatch: inferred type is Int but Unit was expected
Here is the official explanation for explicitly defining the return type of functions with block bodies:
Functions with block body must always specify return types explicitly, unless it's intended for them to return Unit, in which case it is optional. Kotlin does not infer return types for functions with block bodies because such functions may have complex control flow in the body, and the return type will be non-obvious to the reader (and sometimes even for the compiler).
So, the correct way to declare compareTo(MyDate)
is to specify the return type of the function if it includes the block body:
operator fun compareTo(other: MyDate): Int {
when {
year != other.year -> return year - other.year
month != other.month -> return month - other.month
else -> return dayOfMonth - other.dayOfMonth
}
}
This solves another error at the same time since the comparison operator is required to return an Int
.
Upvotes: 2