For the More Curious: File-Level Functions in Java

All of the functions that you have written so far have been defined at the file level in Game.kt. If you are a Java developer, then this may seem surprising to you. In Java, functions and variables can only be defined within classes, a rule that Kotlin does not adhere to.

How is this possible if Kotlin code compiles to Java bytecode to run on the JVM? Does Kotlin not have to play by the same rules? A look at the decompiled Java bytecode for Game.kt should prove illuminating:

    public final class GameKt {
        public static final void main(...) {
            ...
        }

        private static final String formatHealthStatus(...) {
            ...
        }

        private static final void printPlayerStatus(...) {
            ...
        }

        private static final String auraColor(...) {
            ...
        }

        private static final void castFireball(...) {
            ...
        }

        // $FF: synthetic method
        // $FF: bridge method
        static void castFireball$default(...) {
            ...
        }
    }

File-level functions are represented in Java as static methods on a class with a name based on the file in which they are declared in Kotlin. (Method is Java for “function.”) In this case, functions and variables defined in Game.kt are defined in Java in a class called GameKt.

You will see how to declare functions in classes in Chapter 12, but being able to declare functions and variables outside of them gives you more flexibility to define a function that is not tied to a particular class definition. (And if you are wondering what the castFireball$default method in GameKt is all about, this is how default arguments are implemented. You will see this in more detail in Chapter 20.)