X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=examples%2FArrayBasedStorage.pod;h=bff9baaec231d2ea62041ea11e578135ca0c5e28;hb=202ccce01fee680d3637144e98308de85323a1cc;hp=aa174dba5836c5f12d2930c24b604abef657a7e7;hpb=62189f8484905d2cceec70b0a2a508a104e781d7;p=gitmo%2FClass-MOP.git diff --git a/examples/ArrayBasedStorage.pod b/examples/ArrayBasedStorage.pod index aa174db..bff9baa 100644 --- a/examples/ArrayBasedStorage.pod +++ b/examples/ArrayBasedStorage.pod @@ -1,84 +1,15 @@ - -package # hide the package from PAUSE - ArrayBasedStorage::Attribute; - -use strict; -use warnings; - -use Carp 'confess'; - -our $VERSION = '0.01'; - -use base 'Class::MOP::Attribute'; - -sub initialize_instance_slot { - my ($self, $meta_instance, $instance, $params) = @_; - my $init_arg = $self->{init_arg}; - # try to fetch the init arg from the %params ... - my $val; - $val = $params->{$init_arg} if exists $params->{$init_arg}; - # if nothing was in the %params, we can use the - # attribute's default value (if it has one) - if (!defined $val && defined $self->{default}) { - $val = $self->default($instance); - } - $meta_instance->set_slot_value($instance, $self->name, $val); -} - -sub generate_accessor_method { - my $self = shift; - my $meta_class = $self->associated_class; - my $attr_name = $self->name; - return sub { - my $meta_instance = $meta_class->initialize(Scalar::Util::blessed($_[0]))->get_meta_instance; - $meta_instance->set_slot_value($_[0], $attr_name, $_[1]) if scalar(@_) == 2; - $meta_instance->get_slot_value($_[0], $attr_name); - }; -} - -sub generate_reader_method { - my $self = shift; - my $meta_class = $self->associated_class; - my $attr_name = $self->name; - return sub { - confess "Cannot assign a value to a read-only accessor" if @_ > 1; - $meta_class->initialize(Scalar::Util::blessed($_[0])) - ->get_meta_instance - ->get_slot_value($_[0], $attr_name); - }; -} - -sub generate_writer_method { - my $self = shift; - my $meta_class = $self->associated_class; - my $attr_name = $self->name; - return sub { - $meta_class->initialize(Scalar::Util::blessed($_[0])) - ->get_meta_instance - ->set_slot_value($_[0], $attr_name, $_[1]); - }; -} - -sub generate_predicate_method { - my $self = shift; - my $meta_class = $self->associated_class; - my $attr_name = $self->name; - return sub { - defined $meta_class->initialize(Scalar::Util::blessed($_[0])) - ->get_meta_instance - ->get_slot_value($_[0], $attr_name) ? 1 : 0; - }; -} - + package # hide the package from PAUSE ArrayBasedStorage::Instance; use strict; use warnings; +use Scalar::Util qw/refaddr/; use Carp 'confess'; our $VERSION = '0.01'; +my $unbound = \'empty-slot-value'; use base 'Class::MOP::Instance'; @@ -86,45 +17,62 @@ sub new { my ($class, $meta, @attrs) = @_; my $self = $class->SUPER::new($meta, @attrs); my $index = 0; - $self->{slot_index_map} = { map { $_ => $index++ } $self->get_all_slots }; + $self->{'slot_index_map'} = { map { $_ => $index++ } $self->get_all_slots }; return $self; } sub create_instance { my $self = shift; - $self->bless_instance_structure([]); + my $instance = $self->bless_instance_structure([]); + $self->initialize_all_slots($instance); + return $instance; +} + +sub clone_instance { + my ($self, $instance) = shift; + $self->bless_instance_structure([ @$instance ]); } # operations on meta instance -sub get_slot_index_map { (shift)->{slot_index_map} } +sub get_slot_index_map { (shift)->{'slot_index_map'} } + +sub initialize_slot { + my ($self, $instance, $slot_name) = @_; + $self->set_slot_value($instance, $slot_name, $unbound); +} + +sub deinitialize_slot { + my ( $self, $instance, $slot_name ) = @_; + $self->set_slot_value($instance, $slot_name, $unbound); +} sub get_all_slots { my $self = shift; - return sort @{$self->{slots}}; + return sort $self->SUPER::get_all_slots; } sub get_slot_value { my ($self, $instance, $slot_name) = @_; - return $instance->[ $self->{slot_index_map}->{$slot_name} ]; + my $value = $instance->[ $self->{'slot_index_map'}->{$slot_name} ]; + return $value unless ref $value; + refaddr $value eq refaddr $unbound ? undef : $value; } sub set_slot_value { my ($self, $instance, $slot_name, $value) = @_; - $instance->[ $self->{slot_index_map}->{$slot_name} ] = $value; + $instance->[ $self->{'slot_index_map'}->{$slot_name} ] = $value; } -sub initialize_slot { +sub is_slot_initialized { my ($self, $instance, $slot_name) = @_; - $instance->[ $self->{slot_index_map}->{$slot_name} ] = undef; + # NOTE: maybe use CLOS's *special-unbound-value* for this? + my $value = $instance->[ $self->{'slot_index_map'}->{$slot_name} ]; + return 1 unless ref $value; + refaddr $value eq refaddr $unbound ? 0 : 1; } -sub is_slot_initialized { - # NOTE: - # maybe use CLOS's *special-unbound-value* - # for this ? - confess "Cannot really tell this for sure"; -} +sub is_dependent_on_superclasses { 1 } 1; @@ -165,15 +113,17 @@ This is very similar now to the InsideOutClass example, and in fact, they both share the exact same test suite, with the only difference being the Instance metaclass they use. -=head1 AUTHOR +=head1 AUTHORS Stevan Little Estevan@iinteractive.comE +Yuval Kogman Enothingmuch@woobling.comE + =head1 SEE ALSO =head1 COPYRIGHT AND LICENSE -Copyright 2006 by Infinity Interactive, Inc. +Copyright 2006-2008 by Infinity Interactive, Inc. L