JP
02/23/2020, 5:35 AMimport java.util.*
fun getList(): List<Int> {
val arrayList = arrayListOf(1, 5, 2)
Collections.sort(arrayList, object : Comparator<Int> {
override fun compare = {x: Int, y: Int -> y - x}
})
return arrayList
}
gave me error messages:
Object is not abstract and does not implement abstract member public abstract fun compare(p0: Int!, p1: Int!): Int defined in java.util.Comparator
'compare' overrides nothing
Expecting '('
Can someone elaborate these messages?
edit:
additionally when I tried different codes in the line starting with override fun compare
,
1.
override fun compare(x: Int, y: Int) {
return y - x
}
this did not work as well, producing error messages
Return type of 'compare' is not a subtype of the return type of the overridden member 'public abstract fun compare(p0: Int!, p1: Int!): Int defined in java.util.Comparator'
Type mismatch: inferred type is Int but Unit was expected
I don’t understand the error message. Why was the expected type Unit
, not Int
? Shouldn’t the compiler expect the return type as Int
?
BUT
2. with a slight modification,
override fun compare(x: Int, y: Int): Int {
return y - x
}
this worked.
3.
override fun compare(x: Int, y: Int) = y - x
This works also. But in this case, I also didn’t explicitly write the return type, same as approach 1.
What are the differences between them? Why did 1. produce error while the other two didn’t? What’s happening under the hood?Kiryushin Andrey
02/23/2020, 7:10 AMcompare
declaration is syntactically incorrect - it is a function, but it does not have parentheses for arguments and they are required for function declaration - that is what Expecting '('
error is about.
You need a proper function declaration with a matching signature to provide the implementation for interface method and compiler cannot find such function in your object - that's why it throws Object is not abstract and does not implement abstract member
And no, you can't override a function with a lambda expression. If you declare a lambda in a class, it essentially is a property of a functional type, and as such can only override a property of the same type, not a function. The syntax for the functional property declaration will be the following (note that there is no fun
here):
val compare = { x: Int, y: Int -> y - x }
Kiryushin Andrey
02/23/2020, 7:12 AM{}
, otherwise compiler assumes the function returns Unit
. Return type inference works only for single-expression functions.Kiryushin Andrey
02/23/2020, 7:15 AMComparator
is a functional interface, therefore you can replace anonymous object declaration with a lambda expression for its only abstract method implementation and the compiler will create anonymous object under the hood for you:
Collections.sort(arrayList) { x, y -> y - x }
JP
02/23/2020, 7:21 AMComparator
is a functional interface in the next koan link https://play.kotlinlang.org/koans/Introduction/SAM%20conversions/Task.kt
But then here why does one not need to explicitly state the types of x
, y
, and also the return type, whereas in cases above I had to?Kiryushin Andrey
02/23/2020, 7:25 AMJP
02/23/2020, 7:27 AM