NAME
Class::Builder - auto-generator of class accessors/special methods
SYNOPSIS
Creating Class Members (fields):
package SystemUser;
use Class::Builder {
uid => { number => undef },
uname => { string => 'default user' },
group => { arrayref => []},
ctime => { number => time },
disable => { boolean => 0 },
log_count => { counter => 0},
};
1;
# then in your script:
package main;
use SystemUser;
my $user = new SystemUser ({name => 'chopin'});
print $user->uname(), "\n"; # print chopin;
print scalar localtime $user->ctime(), "\n";
foreach my $group ($user->group){
&do_something($group);
}
my $user = new SystemUser ({uname => 'chopin'});
print $user->uname(), "\n"; # print chopin;
print scalar localtime $user->ctime(), "\n";
sub system_user_loggin{
if($user->disable){
die "you account is disabled, contact system administrator.";
}
# ... do some thing
$user->log_count_add;
print "you are logged into the system. you have loged ",$user->log_count," times.";
}
system_user_loggin(); # print $user->log_count as 1.
Special Methods
package SystemUser;
use Class::Builder {
'-methods' => {
constructor => 'create',
dumper => 'as_string',
clone => 'copy',
},
uid => { number => undef },
uname => { string => '' },
};
1;
package main;
use SystemUser;
my $user = SystemUser->create({name=>'mozart'});
my $user_cp = $user->copy;
# deep copy the structure, not only the pointer
print $user_cp->as_string() # dump the contents of $user
There also a function `struct' opened for you, let you create modules `on the fly':
package SystemUser;
use Class::Builder;
struct Machine => {
machine_name => { string => 'default name' },
location => {string => '' }
}; # define Machine before use it.
struct {
uname => {string => ''},
main_machine => { Machine => undef },
}; # implicit class name: 'SystemUser' in this case.
package main;
my $machine = new Machine( machine_name => 'veryslow' );
my $user = new SystemUser( uname => 'mozart', main_machine => $machine );
print $user->main_machine->machine_name();
DESCRIPTION
Class::Builder
is a module helps OOP programmers to create `class's (packages, in terms of perl) in several ways of automation.
If you've used one of Class::MethodMaker
, Class::Struct
or Class::Accessor
, the concept of Class::Builer
is not newer to you. In fact, this module can be viewed as a combination of the above modules. I'm trying to include most frequently used functions, while keep the module as lightweight as possible.
Field Methods:
To create a new member field for you class, simply say:
use Class::Builder {
<fieldname> => { <fieldtype> => <default_vaule>, [ final => 1 ]},
};
where <fieldname> is the name you want to set as a member field, it must be legal as a name of perl function.
If you defined the field as `final', you can not use the accessor methods to change the field's value. But you still can change it by directly access data stored in the object (a blessed hashref).
`final' attribute is ignored by `hashref' and `arrayref' field, under current implementation.
The following field types are available now:
string
You can get/set a string field via functions. For example
$user->name("myname")
change `$user''s name to `myname'. You can even do:
$user->name = "otername";
Then you can access the value by: print $user->name;
number
Provide same functions as string field. (no extra checking for this field under current implementation).
boolean
Boolean field will be set to '1' if you passed a argument has `true' values in perl.
Additionally, for each boolean field
`x'
, you can:$obj->x_rev(); # reverse. 1 to 0, 0 to 1. $obj->x_reset(); # reset to it's default values.
counter
Count is a number fields that provides some additional values:
$obj->x_add(); # x becomes x+1 $obj->x_add(2); # x becomes x+2 $obj->x_remove(); # do the reverse of above $obj->x_set(19); # directly set the value to 19 $obj->x_reset(); # reset to 0 or any value you defined
hashref
There a special methods provides for fields contains reference to hashes and arraies. Those methods are simple wrappers over perl build-in functions, as the following example:
package SysInfo; use Class::Builder { passwd => {hashref => {huang => 'passwdinsecret', phantom=>'longpasswd'}}, }; package main; my $sysinfo = new SysInfo; $sysinfo->passwd->{newuser} = 'validpasswd'; do_something() if($sysinfo->passwd_exists('huang')); foreach my $user ($sysinfo->passwd_keys){ do_something($user); } foreach my $pass ($sysinfo->passwd_values){ checkpasswd($pass); } $sysinfo->passwd_delete('huang');
arrayref
package MusicCD; use Class::Builder { trackList => { arrayref => [qw(track1 silent noise)], }, } package main; my $mcd = new MusicCD; foreach my $tract ($mcd->trackList){ ... } my $arrayref = $mcd->trackList; # use this to get the count my $count = $mcd->trackList_count; $mcd->trackList_push('newTrack'); $mcd->trackList_pop(); # newTrack $mcd->trackList_unshift('firstTrack'); $mcd->trackList_shift(); # firstTract $mcd->trackList_splice(1, 1);
other object
Any other field name will be interpretered as external class names. Sign a default value is little different than other fields:
# if you passes a single scalar, it will be treated as # the constructor of the value: use Class::Builder { filehandler => {IO::File => 'new'}, }; # create a new IO::File object # if you passes a array reference, it will be treated as # ['constructor, arg1, arg2, ...] use Class::Builder { filehandler => {IO::File => ['new', 'filename', 'r']}, }; # this time, open filename for you too. # if a reference of other type passed, it will be treated # as the object itself: my $fh = new IO::File('filename', 'w') or die "$!"; use Class::Builder { filehandler => {IO::File => $fh}, }; # just use $fh
Note at the last example, we do not require
ref $fh
to beIO::File
, so, use a object drived from some subclass of IO::File is allowed.
Two special functions applies for all member fields:
clear('field1', 'field2', ...)
will set member field 'field1', 'field2', ... to
undef
.get('field1', 'field2', ...)
return a list contains values of member fields 'field1', 'field2', ....
Note that currently all types are implemented as a key of a perl hash, so you can assign any scalar value to any field without causing errors. Typically, number
field and string
field have no difference it all, it is introduced only for future development (such as dynamic linkage with databases). I.e, you can sign a perl string to a number field, but we do not recommend you do that.
On-the-Fly Classes
You can use function struct()
in three styles:
struct(\%args)
where
\%args
takes the same form as you used inuse Class::Builder \%args;
Class::Builder
will take the current package as the class name.struct(Classname1 =
\%args1, Classname2=> \%args2, ...)>This form of
struct
creates classes `on the fly', so, you do not need to defineclassname1
,classname2
munually. You can thinks the code:struct(Classname1 => \%args1, Classname2=> \%args2)
as a shortcut as:
package Classname1; use Class::Builder \%args1; 1; package Classname2; use Class::Builder \%args2; 1;
struct([classname =
\%args, classname2=> \%args])>Almost as same as the above case. Passes arguments as a reference of a array is (theorically) little faster than passes them as a legacy array. Use this form if you concerns with perfomance issues.
IMPORTANT:
struct({classname =
\%args, classname2=> \%args})> do not work as you expected. (Class::Builder
interpreted the hashref as arguments for current class, as the first style mentioned above).Note that
package SomeClass; use Class::Builder { ... some defination ... }; struct { ... some defination ... };
is not recommended, any field defined in struct could not get a chance to setup it's default values.
Special Methods
Class::Builder
also has a ability to create special methods:
constructor
By default,
Class::Builder
will create a functionnew()
as the constructor. you can change the name of constructor to others such likecreate()
by defining:use Class::Builder { '-methods' => { constructor => 'create' }, };
or even you can define more than one constructor, each has same functions:
use Class::Builder { '-methods' => { constructor => ['create', 'new'] }, };
you can pass a hash reference to initialize member fields:
package SomeClass; use Class::Builder { '-methods' => { constructor => 'create' }, somefield => { string => '' }, }; 1; package main; my $sc = new SomeClass ({somefield => 'newvalues'});
Pass initial values as a list is also acceptable:
my $sc = new SomeClass (somefield => 'newvalues');
UNTIL you defined any initializers as below.
initializer
You can define one or more initializers, each will by called by constructor (
new()
, by the default) in orders as you defined:package SomeBody; use Class::Builder { '-methods' => {initializer => ['init1', 'init2']}, } sub init1{ ... }; sub init2{ ... };
Then,
init1()
andinit2()
will get called whenever you create a new instance ofSomeBody
:package SystemUser; use Class::Builder { '-methods' => { initializer => ['init1', 'init2'], }, name => {string => 'bethoven'}, }; sub init1{shift->{name} = 'chopin';} sub init2{shift->{name} = 'Walsh';} 1; package main; my $user = new SystemUser( {name => 'mozart'} ); print $user->name(); # print Walsh
You can pass arguments as a array (not a hash reference) to constructor, and all of the initializers will get them also.
INHERITAGE
To create a subclass of Class::Builder, at lease you must define two functions:
struct();
use the following code:
sub struct{ __PACKAGE__->_struct(@_); }
setup();
Do something before
Class::Builder
takes actions.known_types();
If you want to provide some new field types, rewrite this function to avoid fatal errors.
BUGS
This package is not yet well tested.
AUTHOR
Wei, Huang < huang@toki.waseda.jp >
SEE ALSO
5 POD Errors
The following errors were encountered while parsing the POD:
- Around line 813:
'=item' outside of any '=over'
- Around line 859:
You forgot a '=back' before '=head2'
- Around line 863:
'=item' outside of any '=over'
- Around line 937:
You forgot a '=back' before '=head1'
- Around line 960:
You forgot a '=back' before '=head1'