Generics with custom containers
Although Gosu generics are often used with collections and lists, there is no requirement to use
generics only with Collection and List interfaces. Any class
that represents a container for other objects can use Gosu generics to define the type of
items in the container.
Abstract example
Suppose you need to store key-value maps. You can define a class that uses the Object class to define two types of object:
class Mymapping {
function put( key : Object, value : Object) {...}
function get( key : Object) : Object {...}
}
Alternatively, you can use generics to define the class:
class Mymapping<K,V> {
function put( key : K, value : V) {...}
function get( key : K) : V {...}
}
This class enforces strongly typed values at compile time. In the following code, the theValue
variable is strongly typed at compile time as Integer.
var myMap = new Mymapping<String, Integer>
myMap.put("ABC", 29)
var theValue = myMap.get("ABC")Real-world example
Consider an application that tracks the construction of vehicles in multiple factories. You can represent cars with Car objects, trucks with Truck objects, and vans with Van objects. All these classes derive from a root class Vehicle.
Your application uses a custom container object of type FactoryGroup that does not extend a collection class. For this example, assume that each factory only constructs one type of vehicle. A FactoryGroup object can contain multiple Car objects, or multiple Truck objects, or multiple Van objects.
- A
FactoryGroupcontaining one or more Car objects - A
FactoryGroupcontaining one or more Truck objects - A
FactoryGroupcontaining one or more Van objects
public class FactoryGroup<T>FactoryGroup<Car>FactoryGroup<Truck>FactoryGroup<Van>
Consider a method in your application that returns all vehicles in the last step of a multistep manufacturing process. The method definition is like the following line:
public function getLastStepVehicles(groupofvehicles : FactoryGroup<T>) : FactoryGroup<T>By using generics, the method supports all types of FactoryGroup objects. Because the letter
T appears more than once in the method signature, this syntax defines relationships between
the parameter and the return value. The method getLastStepVehicles takes one argument that is
a factory group containing any one vehicle type. The method returns another factory group that is guaranteed to
contain the same type of vehicle.
Alternatively, you could define your method with a bounded wildcard specification for the type:
public function getLastStepVehicles(groupofvehicles : FactoryGroup<T extends Vehicle>) : FactoryGroup<T>By using this approach, your code can make more assumptions about the type of object in the factory group. This
approach also prevents some coding errors, such as accidentally passing
FactoryGroup<String> or FactoryGroup<Integer>, which fail at
compile time. You can discover your coding errors quickly.
