Badger
view release on metacpan or search on metacpan
lib/Badger/Class/Methods.pm view on Meta::CPAN
my ($class, $target, $methods) = shift->args(@_);
my $index = 0;
foreach my $method (@$methods) {
my $i = $index++; # new lexical var for closure
$target->import_symbol(
$method => sub {
return @_ > 1
? ($_[0]->[$i] = $_[1])
: $_[0]->[$i];
}
);
}
}
sub auto_can {
my ($class, $target, $methods) = shift->args(@_);
die "auto_can only support a single method at this time\n"
if @$methods != 1;
my $method = shift @$methods;
croak "Invalid auto_can method specified: $method\n"
if ref $method eq CODE;
# avoid runaways
my $seen = { };
$class->debug("installing AUTOLOAD and can() in $target") if DEBUG;
$target->import_symbol(
can => sub {
my ($this, $name, @args) = @_;
$class->debug("looking to see if $this can $name()") if DEBUG;
# This avoids runaways where can() calls itself repeatedly, but
# doesn't prevent can() from being called several times for the
# same item.
return if $seen->{ $name };
local $seen->{ $name } = 1;
return $this->SUPER::can($name)
|| $this->$method($name, @args);
}
);
$target->import_symbol(
AUTOLOAD => sub {
my ($this, @args) = @_;
my ($name) = ($AUTOLOAD =~ /([^:]+)$/ );
return if $name eq 'DESTROY';
if (my $method = $this->can($name, @args)) {
my $that = class($this);
$class->debug("$class installing $name method in $that") if DEBUG;
$that->method( $name => $method );
return $method->($this, @args);
}
# Hmmm... what if $this isn't a subclass of Badger::Base?
return $this->error_msg( bad_method => $name, ref $this, (caller())[1,2] );
}
);
$class->debug("installed AUTOLOAD and can() in $target") if DEBUG;
}
sub args {
my $class = shift;
my $target = shift;
my $methods = @_ == 1 ? shift : [ @_ ];
# update $target to a Badger::Class object if not already one
$target = class($target)
unless is_object(BCLASS, $target);
# split text string into list ref of method names
$methods = [ split(DELIMITER, $methods) ]
unless ref $methods eq ARRAY;
return ($class, $target, $methods);
}
1;
__END__
=head1 NAME
Badger::Class::Method - metaprogramming module for adding methods to a class
=head1 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';
=head1 DESCRIPTION
This module can be used to generate methods for a class. It can be used
directly, or via the L<accessors|Badger::Class/accessors>,
L<accessors|Badger::Class/accessors> and L<slots|Badger::Class/slots>
export hooks in L<Badger::Class>.
=head1 METHODS
=head2 generate($class,$type,$methods)
This method is a central dispatcher to other methods.
Badger::Class::Methods->generate(
( run in 1.442 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )