Stem Cookbook - World3
NAME
World3 - Mixing class and object Stem cells.
DESCRIPTION
This is an extension of the Stem Cookbook Part 1 & Stem Cookbook Part 2 where we talked about the creation of Stem class and object cells. In this example, we take the idea of a class cell and an object cell and combine them into a single Stem module. We then have the ability of creating multiple cells (registered objects) with their own private data and at the same time have a class cell to manage a global resource.
CREATING THE CELL
The following lists the requirements for creating a Stem object level cell:
An attribute specification
An object constructor
A class registration
CHANGES FROM PART 1 AND PART 2
Most of the code from Part 2 and Part 1 remain the same. We keep the same attribute specification as well as the same object cell constructor (except for a slight modification, see below). You remember from Part 1 that we created a class level Stem cell from the configuration file,
[ class => 'World1', name => 'solar_system',
]
Because we do not have an args field, it means we are creating a class cell. In this example, we want a class cell to be created as a global resource only if an object cell is created. If the class cell is supposed to manage global information for object cells there is no need to create one if an object cell does not exist. To get this type of behavior, we register the class cell from within the Stem module rather than from the configuration file,
Stem::Route::register_class( __PACKAGE__, 'solar_system' );
This line (World3.pm, line 5) effectively registers the class cell with the Stem message routing system using the package name and a name we wish to register the cell as.
We keep referring to the class cell as a global resource, so in this example we create a global resource that the class cell will manage,
my @objects = ();
On line 16 in World3.pm we create an array named objects that will be used to hold a reference to each of the World3 cell objects that are created from the configuration file (Note that this is not a requirement for creating this module and is just used as an example. It could have just as easily been a simple scalar, a hash, some other kind of object, or even nothing!).
In order to populate this array of the objects that are created from the configuration file, we simply add them to the array when they are created in the object cell constructor,
push @objects, $self;
This simply pushes the reference to the newely created World3 object cell onto the objects array. The class cell can now be used to represent the World3 object cells as a group.
The next modification exists in the hello_cmd subroutine. We need a way to distiguish whether or not a message is being sent to an object cell as opposed to a class cell. As you might recall, the perl ref function is used to determine if a scalar refers to a reference or a normal scalar value. If a subroutine is invoked from an object, the first argument of the subroutine will be a reference to the object itself, otherwise, it will be the string name of the class from which the subroutine belongs. The following code demonstrates a new hello_cmd subroutine that makes this distinction and performs accordingly,
sub hello_cmd {
my ($class) = @_;
return "Hello world from $class->{'planet'}\n" if ref $class;
my $response_string = '';
foreach my $obj (@objects) {
$response_string .= "Hello world from $obj->{'planet'}\n";
}
return $response_string;
}
As you can see, we return the familiar "Hello world from $class->{'planet'}" string, but this time we check to make sure $class is a reference before returning the string. If it is not, we know that the hello_cmd was invoked from a message that was intended for the class cell. If this is the case, we concatenate a "Hello, World ..." string for each of the Hello3 object cells that were stored in the objects array and send that string as a response message to the sender.
SEE ALSO
Stem Cookbook Part 1
Stem Cookbook Part 2
Hello3 Module