Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
Badger::Class::MethodsUser Contributed Perl DocumentaBadger::Class::Methods(3)

NAME
       Badger::Class::Method - metaprogramming module for adding methods to a
       class

SYNOPSIS
	   package My::Module;

	   # using the module directly
	   use Badger::Class::Methods
	       accessors => 'foo bar',
	       mutators	 => 'wiz bang';

	   # or	via Badger::Class
	   use Badger::Class
	       accessors => 'foo bar',
	       mutators	 => 'wiz bang';

DESCRIPTION
       This module can be used to generate methods for a class.	It can be used
       directly, or via	the accessors, accessors and slots export hooks	in
       Badger::Class.

METHODS
   generate($class,$type,$methods)
       This method is a	central	dispatcher to other methods.

	   Badger::Class::Methods->generate(
	       accessors => 'foo bar',
	   );

   accessors($class,$methods) /	get($class,$methods)
       This method can be used to generate accessor (read-only)	methods	for a
       class (Badger::Class object) or package name. You can pass a list,
       reference to a list, or a whitespace delimited string of	method names
       as arguments.

	   # these all do the same thing
	   Badger::Class::Methods->accessors('My::Module', 'foo	bar');
	   Badger::Class::Methods->accessors('My::Module', 'foo', 'bar');
	   Badger::Class::Methods->accessors('My::Module', ['foo', 'bar']);

       A method	will be	generated in the target	class for each that returns
       the object member data of the same name.	 The method itself is
       generated by calling the	accessor() method.

   accessor($name)
       This method generates an	accessor method	for accessing the item in an
       object denoted by $name.	 The method is returned	as a code reference.
       It is not installed in the symbol table of any package -	that's up to
       you (or use the accessors() method).

	   my $coderef = Badger::Class::Method->accessor('foo');

       The code	generated is equivalent	to this:

	   sub foo {
	       $_[0]->{	foo };
	   }

   mutators($class,$methods) / set($class,$methods)
       This method can be used to generate mutator (read/write)	methods	for a
       class (Badger::Class object) or package name. You can pass a list,
       reference to a list, or a whitespace delimited string of	method names
       as arguments.

	   # these all do the same thing
	   Badger::Class::Methods->mutators('My::Module', 'foo bar');
	   Badger::Class::Methods->mutators('My::Module', 'foo', 'bar');
	   Badger::Class::Methods->mutators('My::Module', ['foo', 'bar']);

       A method	will be	generated in the target	class for each that returns
       the object member data of the same name.	If an argument is passed to
       the method then the member data is updated and the new value returned.

       The method itself is generated by calling the mutator() method.

   mutator($name)
       This method generates a mutator method for accessing and	updating the
       item in an object denoted by $name. The method is returned as a code
       reference. It is	not installed in the symbol table of any package -
       that's up to you	(or use	the mutators() method).

	   my $coderef = Badger::Class::Method->mutator('foo');

       The code	generated is equivalent	to this:

	   sub foo {
	       @_ == 2
		   ? ($_[0]->{ foo } = $_[1])
		   :  $_[0]->{ foo };
	   }

       Ugly isn't it?	But of course you wouldn't ever	write it like that,
       being a conscientious Perl programmer concerned about the future
       readability and maintainability of your code.  Instead you might	write
       it something like this:

	   sub foo {
	       my $self	= shift;
	       if (@_) {
		   # an	argument implies a set
		   return ($self->{ foo	} = shift);
	       }
	       else {
		   # no	argument implies a get
		   return $self->{ foo };
	       }
	   }

       Or perhaps like this:

	   sub foo {
	       my $self	= shift;
	       # update	value if an argument was passed
	       $self->{	foo } =	shift if @_;
	       return $self->{ foo };
	   }

       Or even like this (my personal favourite):

	   sub foo {
	       my $self	= shift;
	       return @_
		   ? ($self->{ foo } = shift)
		   :  $self->{ foo };
	   }

       Whichever way you do it is a waste of time, both	for you	and anyone who
       has to read your	code at	a later. Seriously, give it up!	Let us
       generate	the methods for	you. We'll not only save you the effort	of
       typing pages of code that no-one	will ever read (or want	to read), but
       we'll also generate the most efficient code for you. The	kind that you
       wouldn't	normally want to handle	by yourself.

       So in summary, using this method	will keep your code clean, your	code
       efficient, and will free	up the rest of the afternoon so	you can	go out
       skateboarding.  Tell your boss I	said it	was OK.

   hash($class,	$methods)
       This method generates methods for accessing or updating items in	a hash
       reference stored	in an object.  In the following	example	we create a
       "users()" method	for accessing the internal "users" hash	reference.

	   package Your::Module;

	   use base 'Badger::Base';
	   use Badger::Class::Methods
	       hash => 'users';

	   sub init {
	       my ($self, $config) = @_;
	       $self->{	users }	= $config->{ users } ||	{ };
	       return $self;
	   }

       The "init()" method copies any "users" passed as	a configuration
       parameter or creates an empty hash reference.

	   my $object =	Your::Module->new(
	       users =>	{
		   tom => 'tom@badgerpower.com',
	       }
	   );

       When called without any arguments, the generated	"users()" method
       returns a reference to the "users" hash array.

	   print $object->users->{ tom };  # tom@badgerpower.com

       When called with	a single non-reference argument, it returns the	entry
       in the hash corresponding to that key.

	   print $object->users('tom');	   # tom@badgerpower.com

       When called with	a single reference to a	hash array, or a list of named
       parameters, the method will add the new items to	the internal hash
       array.  A reference to the hash array is	returned.

	   $object->users({			   # single hash ref
	       dick  =>	'richard@badgerpower.com',
	       harry =>	'harold@badgerpower.com',
	   });

	   $object->users(			   # list of amed parameters
	       dick  =>	'richard@badgerpower.com',
	       harry =>	'harold@badgerpower.com',
	   );

   initialiser($class,$methods)
       This method can be used to create a custom "init()" method for your
       object class. A list, reference to a list, or string of whitespace
       delimited method	names should be	passed an argument(s). A method	will
       be generated which calls	each in	turn, passing a	reference to a hash
       array of	configuration parameters.

	   use Badger::Class::Methods->initialiaser(
	       'My::Module',
	       'init_foo init_bar'
	   )

       The above example will generate an "init()" method in "My::Module"
       equivalent to:

	   sub init {
	       my ($self, $config) = @_;
	       $self->{	config } = $config;
	       $self->init_foo($config);
	       $self->init_bar($config);
	       return $self;
	   }

       It's up to you to implement the "init_foo()" and	"init_bar()" methods,
       or to inherit them from a base class or mixin.

   slots($class,$methods)
       This method can be used to define methods for list-based	object
       classes.	 A list, reference to a	list, or string	of whitespace
       delimited method	names should be	passed an argument(s).	A method will
       be generated for	each item specified.  The first	method will reference
       the first (0th) item in the list, the second method will	reference the
       second (1st), and so on.

	   Badger::Class::Methods->slots('My::Module', 'foo bar');
	   Badger::Class::Methods->slots('My::Module', 'foo', 'bar');
	   Badger::Class::Methods->slots('My::Module', ['foo', 'bar']);

       It is usually called indirectly via the slots export hook in
       Badger::Class.

	   package Badger::Example;

	   use Badger::Class
	       slots =>	'size colour object';

	   sub new {
	       my ($class, @stuff) = @_;
	       bless \@stuff, $class;
	   }

       The above example defines a simple list-based object class with three
       slots: "size", "colour" and "object".  You can use it like this:

	   my $bus = Badger::Test::Slots->new(qw( big red bus ));

	   print $bus->size;	   # big
	   print $bus->colour;	   # red
	   print $bus->object;	   # bus

       The methods generated are mutators.  That is, you can pass an argument
       to update the slot value.

	   $bus->size('large');

   auto_can($class,$method)
       This can	be used	to define a method that	automatically generates	other
       methods on demand.

       Suppose you have	a view class that renders a view of a tree. In classic
       double dispatch style, each node	in the tree calls a method against the
       view object corresponding to the	node's type. A "text" node calls
       "$view->view_text($self)", a "bold" node	calls
       "$view->view_bold($self)", and so on (we're assuming that this is some
       kind of document	object model we're rendering, but it could apply to
       anything).

       Our view	methods	might look something like this:

	   sub view_text {
	       my ($self, $node) = @_;
	       print "TEXT: $node\n";
	   }

	   sub view_bold {
	       my ($self, $node) = @_;
	       print "BOLD: $node\n";
	   }

       This can	get rather repetitive and boring if you've got lots of
       different node types.  So instead of defining all the methods manually,
       you can declare an "auto_can" method that will create methods on
       demand.

	   use Badger::Class
	       auto_can	=> 'can_view';

	   sub can_view	{
	       my ($self, $name) = @_;
	       my $NAME	= uc $name;

	       return sub {
		   my ($self, $node) = @_;
		   print "$NAME: $node";
	       }
	   }

       The method should return	a subroutine reference or any false value if
       it declines to generate a method.  For example, you might want to limit
       the generator method to only creating methods that match	a particular
       format.

	   sub can_view	{
	       my ($self, $name) = @_;

	       # only create methods that are prefixed with 'view_'
	       if ($name =~ s/^view_//)	{
		   my $NAME = uc $name;

		   return sub {
		       my ($self, $node) = @_;
		       print "$NAME: $node";
		   }
	       }
	       else {
		   return undef;
	       }
	   }

       The "auto_can()"	method adds "AUTOLOAD()" and "can()" methods to	your
       class.  The "can()" method first	looks to see if	the method is pre-
       defined (i.e. it	does what the default "can()" method does).  If	it
       isn't, it then calls the	"can_view()" method that we've declared	using
       the "auto_can" option (you can call your	method "auto_can()" if you
       like, but in this case we're calling it "can_view()" just to be
       different).  The	end result is that you can call	"can()"	and it will
       generate	any missing methods on demand.

	   # this calls	can_view() which returns a CODE	sub
	   my $method =	$object->can('view_italic');

       The "AUTOLOAD()"	method is invoked whenever you call a method that
       doesn't exist.  It calls	the "can()" method to automatically generate
       the method and then installs the	new method in the package's symbol
       table.  The next	time you call the method it will be there waiting for
       you.  There's no	need for the "AUTOLOAD()" method to get	involved from
       that point on.

	   # this calls	can_view() to create the method	and then calls it
	   $object->view_cheese('Camembert');	   # CHEESE: Camembert

	   # this directly calls the new method
	   $object->view_cheese('Cheddar');	   # CHEESE: Cheddar

       If your "can_view()" method returns a false value then "AUTOLOAD()"
       will raise the familiar "Invalid	method..." error that you would
       normally	get from calling a non-existent	method.

INTERNAL METHODS
   args(@args)
       This methods inspect the	arguments and performs the necessary
       validation for the accessors(), mutators() and slots() methods.

AUTHOR
       Andy Wardley <http://wardley.org/>

COPYRIGHT
       Copyright (C) 2008-2009 Andy Wardley.  All Rights Reserved.

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

perl v5.24.1			  2010-02-20	     Badger::Class::Methods(3)

NAME | SYNOPSIS | DESCRIPTION | METHODS | INTERNAL METHODS | AUTHOR | COPYRIGHT

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Badger::Class::Methods&sektion=3&manpath=FreeBSD+12.0-RELEASE+and+Ports>

home | help