Kotlin, Kotlin and Kotlin
Kotlin is excellent. Did I mention that? It has all of the benefits of Java such as the rich libraries, LibGDX, with none of the downsides. It's also incredibly succinct.
Lambdas
If I want to run something after a few seconds, I use a Timer class with a method after() that takes () -> Unit as its last parameter.
Here's the signature…
fun after(seconds: Float, run: () -> Unit)
That lets me call it with a lambda as follows…
timer.after(5f) { resetWave() }
For what it's worth, the implementation of after() is incredible short…
fun after(seconds: Float, run: () -> Unit) = q.add(Task(run, now + seconds))
Extension Methods
Another thing that works rather well is Kotlin's implementation of extension methods. C# also has extension methods, but Kotlin's go further. Let's say I want to run all the eligible tasks in the timer's update() method. I could write it all inline in the update() method, checking that the LibGDX BinaryHeap backing the timer isn't empty, peeking the head to see if it's eligible, popping it and invoking it if it is, but that would be rather verbose and would hide my intent.
Or I could do this…
var task = q.nextTask() while (task != null) { task.run() task = q.nextTask() }
Here, q.nextTask() is an extension method on BinaryHeap<Task> that returns null if there isn't an eligible task or the next eligible task if there is. It's implemented as a private method inside Timer, so it has access to its properties, including the all-important now property.
private fun BinaryHeap<Task>.nextTask(): Task? { if (size > 0) { val task = peek() if (task.value <= now) { q.pop() return task } } return null }
Extension Properties
Kotlin also has extension properties. I have an interface Transformable that has properties worldX and worldY. When I use objects that implement Transformable in the renderer, I want to know where they are in relation to its camera. To do that, I add a couple of extension properties on Transformable in the renderer, called cameraX and cameraY. The implementation of cameraX is shown below.
val Transformable.cameraX: Float get() = toCameraX(worldX)
That allows the renderer to do things like this…
batch.draw(image, t.cameraX, t.cameraY)
Delegation
Also, Kotlin's implementation of delegation is something that I haven't seen before. In the following example, class Animal implements Transformable, but the implementation of Transformable is handled by t which by default is of type Transform. That means any call to a method or property on Animal that implements the Transformable interface is automatically delegated to t, without the need to delegate it yourself.
class Animal(x: Float, y: Float, t: Transformable = Transform()) : Transformable by t {
For example, in the following code, the property worldX is implemented by a Transform, without the need for me to write anything more.
var a = Animal(100f, 200f) var x = a.worldX
Conclusion
I am not going to claim to be an expert at Kotlin. I only started using it when I began this project, and have been working my way through the Kotlin koans (found here) on my lunch breaks. But I am very pleased with what I've found so far and I think that I will use it instead of Java in circumstances where that's practical.