Learning Kotlin: Object Expressions and SAM Conversions

Submitted by Robert MacLean on Thu, 06/28/2018 - 09:00

More Information

For the 11th post, we get something new to an old C# person - Object Expressions!

Object Expressions are very similar to Anonymous Classes in Java where you can declare a class inline rather than entirely separately in its own file.

In the first Koan we need to implement Comparator<Int> inline:

  1. fun task10(): List<Int> {
  2.     val arrayList = arrayListOf(1, 5, 2)
  3.     Collections.sort(arrayList, object : Comparator<Int> {
  4.         override fun compare(o1:Int, o2:Int):Int {
  5.             return o2 - o1;
  6.         }
  7.     })
  8.     return arrayList
  9. }

You can see on line 21, we define the new object with the object keyword and then use : Comparator<Int> to state it implements that interface. The Comparator has a single function which needs to be implemented which we do on line 22.

The second Koan takes this further and states if there is a single method in an abstract class or interface then we can use SAM, or Single Abstract Method, to avoid needing the class at all as we just need to implement the single function. To achieve this with the Koan, we use an anonymous function that handles the compare function of the Comparator:

  1. fun task11(): List<Int> {
  2.     val arrayList = arrayListOf(1, 5, 2)
  3.     Collections.sort(arrayList, { x, y -> y - x})
  4.     return arrayList
  5. }

and lastly, if we look back to previous post we can use the extension method to simply it further:

  1. fun task12(): List<Int> {
  2.     return arrayListOf(1, 5, 2).sortedDescending()
  3. }

These Koans have given me more thoughts about the language than probably any previous Koans:

  1. Why do classes which implement an interface use override?
    In C#, when you implement an interface you do not need to state that you are not overriding the functions (see this example). In C# only state that your are overriding when you inherit from a function and you actually override a function. The reason is that an interface in Kotlin is closer to an abstract class than in C#, to the point it can have functionality - yup, interfaces can have functions and logic!
  2. So why does Kotlin have interfaces and abstract classes?
    The key difference is an abstract class can have state while the logic in an interface needs to be stateless!
  3. Why bother having SAM?
    As I was working on the Koan, I was delighted by the SAM syntax... and then I wondered why I needed this at all? Why is Collections.sort taking a class as the second parameter? Why not just pass in a function, since that is all that is actually needed? Both C# and Kotlin supports passing functions so this is possible... but something I never knew about Java is that it doesn't support passing functions! You have to use Callable, a class, to pass functions.