Anonymous inner classes

You can define anonymous inner classes in Gosu from within a class method, similar to usage in Java. The syntax for creating an anonymous inner class is very different from creating a named inner class. Constructing instances of anonymous inner classes is similar in many ways to using the new operator to create instances of a base class. However, you can extend the base class by following the class name with braces ({}) and then adding more variables or methods. If you do not have a more useful base class, use Object.

Example 1

The following class uses an anonymous inner class:

package example

class InnerTest {

  static public function runme() {

    // Create instance of an anonymous inner class that derives from Object
    var counter = new Object() {

      // Anonymous inner classes can have variables (public, private, and so on)
      private var i = 0

      // Anonymous inner classes can have constructors
      construct() {
        print("Value is " + i + " at creation!")
      }

      // Anonymous inner classes can have methods
      public function incrementMe() {
        i = i + 1
        print("Value is " + i)
      }
    }

    // "counter" is a variable containing an instance of a class that has no name, 
    // but derives from Object and adds a private variable and a method

    counter.incrementMe()
    counter.incrementMe()
    counter.incrementMe()
    counter.incrementMe()
    counter.incrementMe()
  }
}

You can use the following code in the Gosu Scratchpad to test this class:

example.InnerTest.runme()

This code prints:

Value is 0 at creation!
Value is 1
Value is 2
Value is 3
Value is 4
Value is 5

Example 2

The following example demonstrates an advanced anonymous inner class. This anonymous inner class derives from a more functional class than Object. In this example, new inner class inherits the constructor and another method.

The following code defines a base class named Vehicle for the inner class:

package example

class Vehicle {
  construct() {
    print("A vehicle was just constructed!")
  }

  function actionOne(s : String) {
    print("actionOne was called with arg " + s)
  }
}

The following code creates a different class that uses Vehicle and defines an anonymous inner class that is based on Vehicle:

package example

class FancyVehicle {

  public function testInner() {

    // Create an inner anonymous class that extends Vehicle
    var test = new Vehicle() {
      public function actionTwo(s : String) {
        print("actionTwo was called with arg " + s)
      }
    }
    test.actionOne( "USA" )
    test.actionTwo( "ABCDEFG" )
  }
}

The inner class that defines the actionTwo method uses the new operator and not the class operator. The new operator defines a new class with no name and then creates one instance of that class.

Create the classes, and then try the following lines in Gosu Scratchpad to test the FancyVehicle class:

var g = new example.FancyVehicle()
g.testInner()

This code prints:

A vehicle was just constructed!
actionOne was called with arg USA
actionTwo was called with arg ABCDEFG

Gosu block shortcut for anonymous classes implementing an interface

In certain cases, you can pass a block as a method argument instead of an instance of an anonymous class. If the method is part of an interface that contains exactly one method, you can pass a block instead of the anonymous class instance. This shortcut is especially helpful for APIs defined to take the type BlockRunnable or Runnable.

See also