Class-MakeMethods
view release on metacpan or search on metacpan
MakeMethods/Composite/Inheritable.pm view on Meta::CPAN
use vars qw( %HashFragments );
sub hash {
(shift)->_build_composite( \%HashFragments, @_ );
}
%HashFragments = (
'' => [
'+init' => sub {
my ($method) = @_;
$method->{hash_key} ||= $_->{name};
$method->{data} ||= {};
},
'do' => sub {
my $method = pop @_;
my $self = shift @_;
if ( scalar(@_) == 0 ) {
my $value = get_vvalue($method->{data}, $self);
if ( $method->{auto_init} and ! $value ) {
$value = set_vvalue( $method->{data}, $self, {} );
}
wantarray ? %$value : $value;
} elsif ( scalar(@_) == 1 ) {
if ( ref($_[0]) eq 'HASH' ) {
%{$method->{data}{$self}} = %{$_[0]};
} elsif ( ref($_[0]) eq 'ARRAY' ) {
my $v_self = find_vself($method->{data}, $self) or return;
return @{ $method->{data}{$v_self} }{ @{$_[0]} }
} else {
my $v_self = find_vself($method->{data}, $self) or return;
return $method->{data}{$v_self}{ $_[0] }
}
} elsif ( scalar(@_) % 2 ) {
Carp::croak "Odd number of items in assigment to $method->{name}";
} else {
if ( ! exists $method->{data}{$self} ) {
my $v_self = find_vself($method->{data}, $self);
$method->{data}{$self} = { $v_self ? %{ $method->{data}{$v_self} } : () };
}
while ( scalar(@_) ) {
my $key = shift();
$method->{data}{$self}->{ $key } = shift();
}
wantarray ? %{$method->{data}{$self}} : $method->{data}{$self};
}
},
],
);
########################################################################
=head2 hook - Overrideable array of subroutines
A hook method is called from the outside as a normal method. However, internally, it contains an array of subroutine references, each of which are called in turn to produce the method's results.
Subroutines may be added to the hook's array by calling it with a blessed subroutine reference, as shown below. Subroutines may be added on a class-wide basis or on an individual object.
You might want to use this type of method to provide an easy way for callbacks to be registered.
package MyClass;
use Class::MakeMethods::Composite::Inheritable ( 'hook' => 'init' );
MyClass->init( Class::MakeMethods::Composite::Inheritable->Hook( sub {
my $callee = shift;
warn "Init...";
} );
my $obj = MyClass->new;
$obj->init();
=cut
use vars qw( %HookFragments );
sub hook {
(shift)->_build_composite( \%HookFragments, @_ );
}
%HookFragments = (
'' => [
'+init' => sub {
my ($method) = @_;
$method->{data} ||= {};
},
'do' => sub {
my $method = pop @_;
my $self = shift @_;
if ( scalar(@_) and
ref($_[0]) eq 'Class::MakeMethods::Composite::Inheritable::Hook' ) {
if ( ! exists $method->{data}{$self} ) {
my $v_self = find_vself($method->{data}, $self);
$method->{data}{$self} = [ $v_self ? @{ $method->{data}{$v_self} } : () ];
}
push @{ $method->{data}{$self} }, map $$_, @_;
} else {
my $v_self = find_vself($method->{data}, $self);
my $subs = $v_self ? $method->{data}{$v_self} : ();
my @subs = ( ( ! $subs ) ? () : @$subs );
if ( ! defined $method->{wantarray} ) {
foreach my $sub ( @subs ) {
&$sub( @{$method->{args}} );
}
} elsif ( ! $method->{wantarray} ) {
foreach my $sub ( @subs ) {
my $value = &$sub( @{$method->{args}} );
if ( defined $value ) {
$method->{result} = \$value;
}
}
} else {
foreach my $sub ( @subs ) {
my @value = &$sub( @{$method->{args}} );
if ( scalar @value ) {
push @{ $method->{result} }, @value;
}
}
( run in 1.351 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )