|
Class::Constructor - Simplify the creation of object constructors |
Class::Constructor - Simplify the creation of object constructors
package MyPackage;
# Note if you don't have the CLASS package installed,
# you can use the __PACKAGE__ keyword instead
use CLASS;
use base qw/ Class::Constructor Class::Accessor /;
my @Accessors = qw(
some_attribute
another_attribute
yet_another_attribute
);
CLASS->mk_accessors(@Accessors);
CLASS->mk_constructor(
Name => 'new',
Auto_Init => \@Accessors,
);
Simplifies the creation of object constructors.
Instead of writing:
sub new {
my $proto = shift;
my $class = ref $proto || $proto;
my $self = {};
bless $self, $class;
my %args = @_;
foreach my $attr ('first_attribute', 'second_attribute') {
$self->$attr($args{$attr});
}
$self->_init();
return $self;
}
You can just write:
CLASS->mk_constructor(
Auto_Init => [ 'first_attribute', 'second_attribute' ],
);
There are other features as well:
Init_Methods method of mk_constructor,
you can have your constructor method automatically call
one or more initialization methods.
For instance, the Fruit class could bless objects
into the Fruit::Apple or Fruit::Orange classes
depending on a parameter passed to the constructor.
See the Subclass_Param manpage for details.
CLASS->mk_constructor(
Name => 'new',
Init_Methods => [ '_init' ],
Subclass_Param => 'Package_Type',
Auto_Init => [ 'first_attribute', 'second_attribute' ],
);
The mk_constructor method creates a constructor named Name in
CLASS's namespace.
new.
Foo->mk_constructor(
Name => 'new',
Init_Methods => '_init',
);
my $object = Foo->new; # This calls $object->_init();
Foo->mk_constructor(
Name => 'new',
Init_Methods => [ '_init', '_startup' ],
);
my $object = Foo->new; # after construction, new()
# calls $object->_init(),
# then $object->_startup()
For each name/value pair passed to the constructor, the constructor
will call the method named name with the parameter of value.
For instance, if you make your constructor with:
Fruit->mk_constructor(
Auto_Init => [ 'size', 'colour' ],
);
And you call the constructor with:
use Fruit;
my $fruit = Fruit->new(
size => 'big',
colour => 'red',
);
Then, internally, the new constructor will automatically call the
following methods:
$fruit->size('big');
$fruit->colour('red');
Note that by default, Class::Constructor converts names to lower
case. See CASE SENSITIVITY, below.
Auto_Init
methods, they will be added to the Auto_Init list.
Fruit->mk_constructor(
Required_Params => [ 'size', 'price' ],
);
package main;
use Fruit;
my $fruit = Fruit->new; # error, missing size, price
my $fruit = Fruit->new( # error: missing price
size => 'big'
);
my $fruit = Fruit->new( # okay
size => 'big',
price => 0.25,
);
CASE SENSITIVITY, below.
Disable_Case_Mangling, above.
CASE SENSITIVITY, below.
CASE SENSITIVITY, below.
Required_Params and the special Subclass_Param. See CASE
SENSITIVITY, below.
# Fruit.pm:
package Fruit;
Fruit->mk_constructor(
Name => 'new',
Subclass_Param => 'Type',
);
sub has_core { 0 };
# Fruit/Apple.pm:
package Fruit::Apple;
use base 'Fruit';
sub has_core { 1 };
# main program:
package main;
my $apple = Fruit->new(
Type => 'Apple',
);
if ($apple->has_core) {
print "apples have cores!\n";
}
Subclass_Param
will be loaded or not. This is mainly useful if you are writing
test scripts and you want to load in your packages manually.
For instance:
# Fruit.pm:
package Fruit;
Fruit->mk_constructor(
Name => 'new',
Subclass_Param => 'type',
Dont_Load_Subclass_Param => 'Dont_Load_Subclass',
);
# main program:
package main;
my $apple = Fruit->new(
Type => 'Apple',
Dont_Load_Subclass => 1,
);
Now when the $apple object is created, the constructor makes no
attempt to require the Fruit::Apple module.
By default, attribute names are forced to lower case and
the case of Auto_Init parameter names passed to the constructor
doesn't matter.
So the following call to a constructor:
my $fruit = Fruit->new(
SiZE => 'big',
colOUR => 'red',
);
Is actually equivalent to:
my $fruit = Fruit->new();
$fruit->size('big');
$fruit->colour('red');
You can disable this behaviour by setting Disable_Case_Mangling
to a true value:
package Fruit;
Fruit->mk_constructor(
Disable_Case_Mangling => 1,
);
Now the parameters are left unchanged:
my $fruit = Fruit->new(
SiZE => 'big',
colOUR => 'red',
);
# equivalent to:
my $fruit = Fruit->new();
$fruit->SiZE('big');
$fruit->colOUR('red');
Similarly for class names as passed via Subclass_Param, they are
converted to lower case and then the first letter is uppercased.
# the following creates a Fruit::Apple
my $apple = Fruit->new(
Type => 'APPLE',
);
This behaviour is also disabled via Disable_Case_Mangling:
package Fruit;
Fruit->mk_constructor(
Subclass_Param => 'Type',
Disable_Case_Mangling => 1,
);
# the following creates a Fruit::APPLE
my $apple = Fruit->new(
Type => 'APPLE',
);
Note that this is an advanced feature with limited use, so you can probably skip it.
If you want to customize the way Class::Constructor changes method
names, you can pass subroutines to do the work:
package Fruit;
Fruit->mk_constructor(
Subclass_Param => 'Type',
Method_Name_Normalizer => sub { '_' . lc $_[0] }, # precede lc methods with underscore
Param_Name_Normalizer => sub { uc $_[0] }, # params compared as upper case
Class_Name_Normalizer => sub { uc $_[0] }, # class names to uppercase
Required_Params => [ 'Size' ],
);
# the following creates a Fruit::APPLE
my $apple = Fruit->new(
Type => 'apple',
SiZE => 'big',
colOUR => 'red',
);
# and the above is equivalent to:
my $apple = Fruit->new(
type => 'apple',
);
$apple->_SiZE('big');
$apple->_colOUR('red');
In the example above, the Method_Name_Normalizer causes auto_init to
make convert parameter names into method names as follows:
SiZE => _size
colOUR => _colour
The Class_Name_Normalizer converts the value of Type (the
Subclass_Param) into method names as follows:
apple => APPLE
The Param_Name_Normalizer converts param names to upper case before
comparing them. So Subclass_Param is specified to be Type, and is
eventually passed as type. But since both are normalized to TYPE,
the match is found.
Michael Graham <mag-perl@occamstoothbrush.com>
Copyright (C) 2001 Michael Graham. All rights reserved. This program is free software. You can use, modify, and distribute it under the same terms as Perl itself.
The latest version of this module can be found on http://www.occamstoothbrush.com/perl/
|
Class::Constructor - Simplify the creation of object constructors |