NAME
UNIVERSAL::Object - A useful base class
VERSION
version 0.09
SYNOPSIS
package Person;
use strict;
use warnings;
our @ISA = ('UNIVERSAL::Object');
our %HAS = (
name => sub { die 'name is required' }, # required in constructor
age => sub { 0 }, # w/ default value
gender => sub {}, # no default value
);
sub name { $_[0]->{name} }
sub age { $_[0]->{age} }
sub gender { $_[0]->{gender} }
package Employee;
use strict;
use warnings;
our @ISA = ('Person');
our %HAS = (
%Person::HAS, # inheritance :)
job_title => sub { die 'job_title is required' },
manager => sub {},
);
sub job_title { $_[0]->{job_title} }
sub manager { $_[0]->{manager} }
# ...
my $ceo = Employee->new(
name => 'Alice',
title => 'CEO',
);
my $manager = Employee->new(
name => 'Bob',
title => 'Middle Manager',
manager => $ceo,
);
my $pawn = Employee->new(
name => 'Joe',
title => 'Line Worker',
manager => $manager,
);
DESCRIPTION
This is a simple base class that provides a protocol for object construction and destruction. It aims to be as simple as possible while still being complete.
SLOT MANAGEMENT
One of the key contributions of this module is to provide a mechanism for declaring the slots that a given class is expected to have. These are used in the object construction process to ensure that all slots are created and initialized.
%HAS
This is a public (our
) package variable that contains an entry for each slot expected in the instance. The key is the slot's name, while the value is a CODE reference which, when called, will produce a default value for the slot.
NOTE: No inheritance of slot definitions is done between classes, this is left as an exercise to the author, however it is easily accomplished with the pattern shown above in the SYNOPSIS.
SLOTS ($class)
This is an accessor method for the %HAS
variable in the $class
package.
NOTE: If you choose to store the slot definitions elsewhere (not in %HAS
) or store them in a different form (not key => CODE
hash entries), it is possible to then override this method to return the expected values in the expected form.
INSTANCE REPRESENTATION
REPR
This returns a new HASH reference to use as the instance.
NOTE: If you wish to use a different instance type of some kind then you will need to override this method.
NOTE: The HASH that gets returned from here will eventually be blessed, which means you are limited to tie
or XS MAGIC
based solutions if you want this HASH reference to behave differently.
CONSTRUCTION PROTOCOL
Once we know the expected slots it is very easy to create a default constructor. This is the second key contribution of this module, to provide a consistent and complete protocol for the construction and destruction of instances.
NOTE: The method documentation is meant to be read from top to bottom, in that they are documented in the same order they are called.
new ($class, @args)
This is the entry point for object construction, from here the @args
are passed into BUILDARGS
. The return value of new
should always be a fully constructed and initialized instance.
BUILDARGS ($class, @args)
This method takes the original @args
to the new
constructor and is expected to turn them into a canonical form, which is a HASH ref of name/value pairs. This form is considered a prototype candidate for the instance, and what BLESS
and subsequently CREATE
expect to receive.
NOTE: The values in the prototype candidate should be shallow copies of what was originally contained in @args
, but this is not actually enforced, just suggested to provide better ownership distinctions.
BLESS ($class, $proto)
This method receives the $proto
candidate from BUILDARGS
and from it, ultimately constructs a blessed instance of the class.
This method really has two responsibilities, first is to call CREATE
, passing it the $proto
instance. Then it will take the return value of CREATE
and bless
it into the $class
.
NOTE: This method is mostly here to make it easier to override the CREATE
method, which, along with the REPR
method, can be used to change the behavior and/or type of the instance structure. By keeping the bless
work here we make the work done in CREATE
simpler with less mechanics.
CREATE ($class, $proto)
This method receives the $proto
candidate from BLESS
and return from it an unblessed instance structure that BLESS
will then bless
into the $class
.
First it must call SLOTS
(described above), followed by REPR
(also described above) to get both the slot definitions and a newly minted HASH ref instance. Using these two things, along with the $proto
candidate, we construct a complete blessed instance. This is accomplished by looping through the list of slots, using values in the $proto
when available, otherwise using the slot initializers. The final unblessed HASH ref based instance is then returned.
NOTE: If you wish to use a different instance type of some kind then you will need to override this method.
BUILD ($self, $proto)
The newly blessed instance supplied by BLESS
must still be initialized. We do this by calling all the available BUILD
methods in the inheritance hierarchy in the correct (reverse mro) order.
BUILD
is an optional initialization method which receives the blessed instance as well as the prototype candidate. There are no restrictions as to what this method can do other then just common sense.
NOTE: It is worth noting that because we call all the BUILD
methods found in the object hierarchy, the return values of these methods are completely ignored.
DESTRUCTION PROTOCOL
The last thing this module provides is an ordered destruction protocol for instances.
DEMOLISH ($self)
This is an optional destruction method, similar to BUILD
, all available DEMOLISH
methods are called in the correct (mro) order by DESTROY
.
DESTROY ($self)
The sole function of this method is to kick off the call to all the DEMOLISH
methods during destruction.
SEE ALSO
AUTHOR
Stevan Little <stevan@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2016, 2017 by Stevan Little.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.