Parameterizing a class

To specify a class that operates with a generic type, define the class with the angle bracket notation CLASSNAME<GENERIC_TYPE_WILDCARD>. By convention, for GENERIC_TYPE_WILDCARD, use a one-letter name, preferably T. For example, you could define a class MyClass as MyClass<T>.

In the following example, the class Genericstest has one method that returns the first item in a list. Gosu strongly types the return value to match the type of the items in the collection:

class GenericsTest<T> {
  // Print out (for debugging) and then return the first item in the list, strongly typed
  public function printAndReturnFirst(aList : ArrayList<T>) : T {
    print(aList[0])
    return aList[0] 
  }
}

Other code can use this class and pass an array list of any type to the method:

var myStrings = new ArrayList<String>(){"a", "abcd", "ab", "abc"}

var t = new GenericsTest<String>()
var first = t.printAndReturnFirst(myStrings)

The variable first is strongly typed as String at compile time because the code uses a method that was defined with generics.

Because the code is strongly typed at compile time, the reliability of the code improves at run time.

Instantiating a generic class

You can instantiate a generic class in the following ways:
  • Using the type token for the type parameter requires information about the type at run time. If you instantiate a generic class in this way in a parameterized method, you must use the reified keyword in the method declaration. This instantiation creates a strongly typed object that uses the explicit type that is reified by the method. For example, in the following lines of code, the type of the variable x is GenericsTest<T> where T is the type of the method parameter t:
    public reified function makeANewGenericOfSpecifiedType<T>(t : T) {
      var x = new GenericsTest<T>()
    }
  • Specifying the type of the type parameter creates a strongly typed object that uses the explicit type. For example, in the following line of code, the type of the variable x is GenericsTest<Integer>:
    public function makeANewGenericOfSpecificType() {
      var x = new GenericsTest<Integer>()
    }

    You can include this instantiation of GenericsTest in a parameterized method without using the reified keyword because you have provided Gosu with the necessary information for the type parameter.

  • Omitting the type parameter creates a strongly typed object that uses the least restrictive type of the bound. For example, in the following line of code, the type of the variable x is GenericsTest<Object>:
    public function makeANewGenericOfNonspecificType() {
      var x = new GenericsTest()
    }

    You can include this instantiation of GenericsTest in a parameterized method without using the reified keyword because Gosu substitutes the least restrictive type that is available for the type parameter.

Enhancements of generic classes

If you create an enhancement of a generic class, you must use the correct syntax:

  • For a generic enhancement, you parameterize both the enhancement name and the class name. For example, the declaration of a generic enhancement to the GenericsTest class looks like the following line.
    enhancement GenericsTest_Enh<T> : GenericsTest<T>
  • For an enhancement that applies to a specific type on the generic class, you specify the type only on the class name. For example, the declaration of an enhancement to the String type of the GenericsTest class looks like the following line.
    enhancement GenericsTest_StringEnh : GenericsTest<String>

See also