Curtis "Ovid" Poe

NAME

Class::BuildMethods - Lightweight implementation-agnostic generic methods.

VERSION

Version 0.22

SYNOPSIS

    use Class::BuildMethods 
        'name',
        rank => { default  => 'private' },
        date => { validate => \&valid_date };

DESCRIPTION

This class allows you to quickly add simple getter/setter methods to your classes with optional default values and validation. We assume no implementation for your class, so you may use a standard blessed hashref, blessed arrayref, inside-out objects, etc. This module does not alter anything about your class aside from installing requested methods and optionally adding a DESTROY method. See "CLEANING UP" for more information, particularly the destroy method.

BASIC METHODS

 package Foo;
 use Class::BuildMethods qw/name rank/;
 
 sub new {
   ... whatever implementation you need
 }

 # later

 my $foo = Foo->new;
 $foo->name('bob');
 print $foo->name;   # prints 'bob'

Using a simple list with Class::BuildMethods adds those methods as getters/setters to your class.

Note that when using a method as a setter, you may only pass in a single value. Arrays and hashes should be passed by reference.

DEFAULT VALUES

 package Foo;
 use Class::BuildMethods
   'name',
   rank => { default => 'private' };

 # later

 my $foo = Foo->new;
 print $foo->rank;   # prints 'private'
 $foo->rank('corporal');
 print $foo->rank;   # prints 'corporal'

After any method name passed to Class::BuildMethods, you may pass it a hash reference of constraints. If a key of "default" is found, the value for that key will be assigned as the default value for the method.

VALIDATION

 package Drinking::Buddy;
 use Class::BuildMethods;
   'name',
   age => {
     validate => sub {
        my ($self, $age) = @_;
        die "Too young" if $age < 21;
     }
   },
   drinking_age => {
     class_data => 1,
     default    => 21
   };

 # later

 my $bubba = Drinking::Buddy->new;
 $bubba->age(18);            # fatal error
 $bubba->age(21);            # Works
 print $bubba->age;          # prints '21'
 print $bubba->drinking_age; # prints '21'

 my $jimbo = Drinking::Buddy->new;
 print $jimbo->drinking_age; # prints '21'
 $jimbo->drinking_age(18);   # UK drinking age
 print $jimbo->drinking_age; # prints '18'
 print $bubba->drinking_age; # prints '18'

If a key of "validate" is found, a subroutine is expected as the next argument. When setting a value, the subroutine will be called with the invocant as the first argument and the new value as the second argument. You may supply any code you wish to enforce validation.

ADDING METHODS AT RUNTIME

build

  Class::BuildMethods->build(
    'name',
    rank => { default => 'private' }
  );

This allows you to add the methods at runtime. Takes the same arguments as the import list to the class.

CLASS DATA

Class data are data which are shared by all members of a class. For example, if you create a Universe class, it's reasonable to assume that they will all share the same value for PI (~ 3.14159), assuming you're really keen on the anthropic principle and take it too far. You do this by simply specifying a method as class data:

 package Universe;

 use Class::BuildMethods
   pi => {
     class_data => 1,
     default    => 3.1415927,
   };

The default is not mandatary for class data, but it's more commonly used than for instance data. The validation property is still supported.

Note that if you inherit a class method, the inherited class will also share this class data:

 package Universe;

 use Class::BuildMethods
   pi => {
     class_data => 1,
     default    => 3.1415927,
   };

 sub new { bless {}, shift }

 package Universe::Fantasy;
 use base 'Universe';

In the above example, both Universe and Universe::Fantasy will share the value of pi and changing the value in either the superclass or subclass will change the value for the other.

If you wish to be able to override the class data value, your subclass must also declare the class data using Class::BuildMethods.

 package Universe;

 use Class::BuildMethods
   pi => {
     class_data => 1,
     default    => 3.1415927,
   };

 sub new { bless {}, shift }

 package Universe::Roman;
 use base 'Universe';

 # Note that the story that ancient Romans used '3' for the value of pi is
 # probably apocryphal.

 use Class::BuildMethods
   pi => {
     class_data => 1,
     default    => 3,
   };
 

With the above code, the value of pi is not shared between the classes. If you want the Universe::Roman class to have the initial value for pi but later be able to change it independently, do something like this:

 package Universe::Roman;
 use base 'Universe';

 # Note that the story that ancient Romans used '3' for the value of pi is
 # probably apocryphal.

 use Class::BuildMethods
   pi => {
     class_data => 1,
   };
 
 sub new {
    my $class = shift;
    $class->pi($class->SUPER::pi);
    return bless {}, $class;
 }
 

CLEANING UP

destroy

  Class::BuildMethods->destroy($instance);

This method destroys instance data for the instance supplied.

Ordinarily you should never have to call this as a DESTROY method is installed in your namespace which does this for you. However, if you need a custom destroy method, provide the special [NO_DESTROY] token to Class::BuildMethods when you're creating it.

 use Class::BuildMethods qw(
    name
    rank
    serial
    [NO_DESTROY]
 );

 sub DESTROY {
   my $self shift;
   # whatever cleanup code you need
   Class::BuildMethods->destroy($self);
 }

reset

  Class::BuildMethods->reset;   # assumes current package
  Class::BuildMethods->reset($package);

This methods deletes all of the values for the methods added by Class::BuildMethods. Any methods with default values will now have their default values restored. It does not remove the methods. Returns the number of methods reset.

reclaim

  Class::BuildMethods->reclaim;   # assumes current package
  Class::BuildMethods->reclaim($package);
 

Like reset but more final. Removes any values set for methods, any default values and pretty much any trace of a given module from this package. It does not remove the methods. Any attempt to use the the autogenerated methods after this method is called is not guaranteed.

packages

  my @packages = Class::BuildMethods->packages;

Returns a sorted list of packages for which methods have been built. If reclaim has been called for a package, this method will not return that package. This is generally useful if you need to do a global code cleanup from a remote package:

 foreach my $package (Class::BuildMethods->packages) {
    Class::BuildMethods->reclaim($package);
 }
 # then whatever teardown you need

In reality, you probably will never need this method.

DEBUGGING

dump

  my $hash_ref = Class::BuildMethods->dump($object);

The dump() method returns a hashref. The keys are the method names and the values are whatever they are currently set to. This method is provided to ease debugging as merely dumping an inside-out object generally does not return its structure.

CAVEATS

Some people will not be happy that if they need to store an array or a hash they must pass them by reference as each generated method expects a single value to be passed in when used as a "setter". This is because this module is designed to be simple. It's very lightweight and very fast.

Note that you cannot automatically serialize the data herein. The reason for this is fairly simple: you can add extra attributes with this module, but since it makes no implementation assumptions, it doesn't know how your code stores its data. If you need to serialize your objects, use the &dump method to fetch the attribute values from Class::BuildMethods and handle the serialization manually.

When in DESTROY is invoked, class data is not removed because other instances may have that data.

AUTHOR

Curtis "Ovid" Poe, <ovid@cpan.org>

ACKNOWLEDGEMENTS

Thanks to Kineticode, Inc. for supporting development of this package.

BUGS

Please report any bugs or feature requests to bug-class-buildmethods@rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Class-BuildMethods. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

COPYRIGHT & LICENSE

Copyright 2005 Curtis "Ovid" Poe, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.




Hosting generously
sponsored by Bytemark