Blocks as shortcuts for anonymous classes

In some cases, you can pass a block as a method argument instead of an anonymous class instance. You can pass a block if the method argument is an implementation of a functional interface. A functional interface contains exactly one abstract method. For example, the Gosu interface type BlockRunnable or the Java interface type Runnable are both functional interfaces that contain a single method called run. Passing a block is much more concise than passing an anonymous class instance. This Gosu coding style works with interfaces that were originally implemented in either Gosu or Java. The parameters of the block must be the same number and type as the parameters to the single method of the interface. The return type of the block must be the same as the return type of that method.

For example, suppose a method signature looks like the following:

public function doAction(b : BlockRunnable)

You can call this method using a block:

obj.doAction(\ -> print("Do your action here"))

As a naming convention, if an API uses a type with a name that contains the word Block, you can probably use a block for that type.

This technique works with any interface, including interfaces defined as inner interfaces within another interface.

Example

This example demonstrates the use of a block argument for an inner functional interface that an outer interface defines. The MyCallbackHandler interface contains an inner functional interface called MyCallbackHandler.CallbackBlock. This functional interface implements a single method named run, similar to the Runnable interface. Instead of creating an anonymous class to use the inner interface, use a block that takes no arguments and has no return value.

This Java code defines the MyCallbackHandler interface:

public interface MyCallbackHandler {

  // A functional interface within this interface
  public interface CallbackBlock {
    public void run() throws Throwable;
  }

// ...

  public void execute(CallbackBlock block) throws Throwable;
}

This Gosu code creates the anonymous class explicitly:

public function messageReceived(final messageId : int) : void {

  var _callbackHandler : MyCallbackHandler
  // Create an anonymous class that implements the inner interface
  var myBlock : _callbackHandler.CallbackBlock = new MyCallbackHandler.CallbackBlock() {

    // Implement the run() method in the interface
    public function run() : void { /* Your Gosu statements here */ }
  }

  // Pass the anonymous inner class with the one method
  _callbackHandler.execute(myBlock)
}

You can code the method more concisely by using a block:

public function messageReceived(messageId : int) {
  _callbackHandler.execute(\ -> { /* Your Gosu statements here */ })
}