Abstract-Meta-Class
view release on metacpan or search on metacpan
lib/Abstract/Meta/Class.pm view on Meta::CPAN
=head1 SYNOPSIS
package Dummy;
use Abstract::Meta::Class ':all';
has '$.attr1' => (default => 0);
has '%.attrs2' => (default => {a => 1, b => 3}, item_accessor => 'attr2');
has '@.atts3' => (default => [1, 2, 3], required => 1, item_accessor => 'attr3');
has '&.att3' => (required => 1);
has '$.att4' => (default => sub { 'stuff' } , required => 1);
my $dummt = Dummy->new(
att3 => 3,
);
use Dummy;
my $obj = Dummy->new(attr3 => sub {});
my $attr1 = $obj->attr1; #0
$obj->set_attr1(1);
$obj->attr2('c', 4);
$obj->attrs2 #{a => 1, b => 3. c => 4};
my $val_a = $obj->attr2('a');
my $item_1 = $obj->attr3(1);
$obj->count_attrs3();
$obj->push_attrs3(4);
=head1 DESCRIPTION
Meta object protocol implementation,
=head2 hash/array storage type
To speed up bless time as well optimise memory usage you can use Array storage type.
(Hash is the default storage type)
package Dummy;
use Abstract::Meta::Class ':all';
storage_type 'Array';
has '$.attr1' => (default => 0);
has '%.attrs2' => (default => {a => 1, b => 3}, item_accessor => 'attr2');
has '@.attrs3' => (default => [1, 2, 3], required => 1, item_accessor => 'attr3');
has '&.attr4' => (required => 1);
has '$.attr5';
has '$.attr6' => (default => sub { 'stuff' } , required => 1);
my $dummy = Dummy->new(
attr4 => sub {},
);
use Data::Dumper;
warn Dumper $dummy;
# bless [0, {a =>1,b => 3}, [1,2,3],sub{},undef,sub {}], 'Dummy'
=head2 simple validation and default values
package Dummy;
use Abstract::Meta::Class ':all';
has '$.attr1' => (default => 0);
has '&.att3' => (required => 1);
use Dummy;
my $obj = Dummy->new; #dies - att3 required
=head2 utility methods for an array type
While specyfing array type of attribute
the following methods are added (count || push || pop || shift || unshift)_accessor.
package Dummy;
use Abstract::Meta::Class ':all';
has '@.array' => (item_accessor => 'array_item');
use Dummy;
my $obj = Dummy->new;
$obj->count_array();
$obj->push_array(1);
my $x = $obj->array_item(0);
my $y = $obj->pop_array;
#NOTE scalar, array context sensitive
my $array_ref = $obj->array;
my @array = $obj->array;
=head2 item accessor method for complex types
While specyfing an array or a hash type of attribute then
you may specify item_accessor for get/set value by hash key or array index.
package Dummy;
use Abstract::Meta::Class ':all';
has '%.hash' => (item_accessor => 'hash_item');
use Dummy;
my $obj = Dummy->new;
$obj->hash_item('key1', 'val1');
$obj->hash_item('key2', 'val2');
my $val = $obj->hash_item('key1');
lib/Abstract/Meta/Class.pm view on Meta::CPAN
=head2 external attributes storage
You may want store attributes values outside the blessed reference, then you may
use transistent keyword (Inside Out Objects)
package Transistent;
use Abstract::Meta::Class ':all';
has '$.attr1';
has '$.x' => (required => 1);
has '$.t' => (transistent => 1);
has '%.th' => (transistent => 1);
has '@.ta' => (transistent => 1);
use Transistent;
my $obj = Transistent->new(attr1 => 1, x => 2, t => 3, th => {a =>1}, ta => [1,2,3]);
use Data::Dumper;
print Dumper $obj;
Cleanup and DESTORY methods are added to class, that delete externally stored attributes.
=head2 METHODS
=over
=item new
=cut
sub new {
my $class = shift;
my $self = bless {}, $class;
unshift @_, $self;
&apply_contructor_parameters;
}
=item install_cleanup
Install cleanup method
=cut
sub install_cleanup {
my ($self) = @_;
my $attributes;
return if $self->has_cleanup_method;
add_method($self->associated_class, 'cleanup' , sub {
my $this = shift;
my $has_transistent;
my $attributes ||= $self ? $self->all_attributes : [];
for my $attribute (@$attributes) {
$attribute or next;
$has_transistent = 1 if($attribute->transistent);
if($attribute->the_other_end) {
$attribute->deassociate($this);
my $accessor = "set_" . $attribute->accessor;
$this->$accessor(undef);
}
}
Abstract::Meta::Attribute::Method::delete_object($this) if $has_transistent;
});
$self->set_cleanup_method(1);
}
=item install_destructor
Install destructor method
=cut
sub install_destructor {
my ($self) = @_;
return if $self->has_destory_method;
add_method($self->associated_class, 'DESTROY' , sub {
my $this = shift;
$this->cleanup;
$this;
});
$self->set_destroy_method(1);
}
=item install_constructor
Install constructor
=cut
sub install_constructor {
my ($self) = @_;
add_method($self->associated_class, 'new' ,
$self->storage_type eq 'Array' ?
sub {
my $class = shift;
my $this = bless [], $class;
unshift @_, $this;
&apply_contructor_parameters;
}: sub {
my $class = shift;
my $this = bless {}, $class;
unshift @_, $this;
&apply_contructor_parameters;
});
}
=item apply_contructor_parameters
Applies constructor parameters.
=cut
{
sub apply_contructor_parameters {
my ($self, @args) = @_;
lib/Abstract/Meta/Class.pm view on Meta::CPAN
=item set_initialise_method
Mutator sets initialise_method for the meta class
=cut
sub set_initialise_method { $_[0]->{'$.initialise_method'} = $_[1]; }
=item associated_class
Returns associated class name
=cut
sub associated_class { shift()->{'$.associated_class'} }
=item set_associated_class
Mutator sets associated class name
=cut
sub set_associated_class { $_[0]->{'$.associated_class'} = $_[1]; }
=item all_attributes
Returns all_attributes for all inherited meta classes
=cut
sub all_attributes {
my $self = shift;
if(my @super_classes = $self->super_classes) {
my %attributes;
foreach my $super (@super_classes) {
my $meta_class = meta_class($super) or next;
$attributes{$_->name} = $_ for @{$meta_class->all_attributes};
}
$attributes{$_->name} = $_ for @{$self->attributes};
return [values %attributes];
}
$self->attributes;
}
=item attribute
Returns attribute object
=cut
sub attribute {
my ($self, $name) = @_;
my $attributes = $self->all_attributes;
my @result = (grep {$_->accessor eq $name} @$attributes);
@result ? $result[0] : undef;
}
=item super_classes
=cut
sub super_classes {
my $self = shift;
no strict 'refs';
my $class = $self->associated_class;
@{"${class}::ISA"};
}
{
my %meta;
=item install_meta_class
Adds class to meta repository.
=cut
sub install_meta_class {
my ($class) = @_;
$meta{$class} = __PACKAGE__->new(
associated_class => $class,
attributes => [],
initialise_method => 'initialise'
);
add_method($class, 'meta', sub{$meta{$class}});
}
=item meta_class
Returns meta class object for passed in class name.
=cut
sub meta_class {
my ($class) = @_;
install_meta_class($class)unless $meta{$class};
$meta{$class};
}
}
=item add_attribute
=cut
sub add_attribute {
my ($self, $attribute) = @_;
$self->install_attribute_methods($attribute);
push @{$self->attributes}, $attribute;
( run in 1.737 second using v1.01-cache-2.11-cpan-d80b1682f3f )