X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=examples%2FInsideOutClass.pod;h=1018c0bd27f5c6598e13faf37df6e9e6ace30a5c;hb=c0fcd6ab4d6e37bb8c1b1f39f130a80ae9e419dc;hp=aaf581ada2d44298599854366730294235bc3a6b;hpb=49c93440bd912ed231b8ab8e93a8e9ac7328fdc7;p=gitmo%2FClass-MOP.git diff --git a/examples/InsideOutClass.pod b/examples/InsideOutClass.pod index aaf581a..1018c0b 100644 --- a/examples/InsideOutClass.pod +++ b/examples/InsideOutClass.pod @@ -1,4 +1,91 @@ +package # hide the package from PAUSE + InsideOutClass::Attribute; + +use strict; +use warnings; + +our $VERSION = '0.02'; + +use Carp 'confess'; +use Scalar::Util 'refaddr'; + +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); + } + my $_meta_instance = $self->associated_class->get_meta_instance; + $_meta_instance->initialize_slot($instance, $self->name); + $_meta_instance->set_slot_value($instance, $self->name, $val); +} + +sub accessor_metaclass { 'InsideOutClass::Method::Accessor' } + +package # hide the package from PAUSE + InsideOutClass::Method::Accessor; + +use strict; +use warnings; + +our $VERSION = '0.01'; + +use Carp 'confess'; +use Scalar::Util 'refaddr'; + +use base 'Class::MOP::Method::Accessor'; + +## Method generation helpers + +sub generate_accessor_method { + my $attr = (shift)->associated_attribute; + my $meta_class = $attr->associated_class; + my $attr_name = $attr->name; + return sub { + my $meta_instance = $meta_class->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 $attr = (shift)->associated_attribute; + my $meta_class = $attr->associated_class; + my $attr_name = $attr->name; + return sub { + confess "Cannot assign a value to a read-only accessor" if @_ > 1; + $meta_class->get_meta_instance + ->get_slot_value($_[0], $attr_name); + }; +} + +sub generate_writer_method { + my $attr = (shift)->associated_attribute; + my $meta_class = $attr->associated_class; + my $attr_name = $attr->name; + return sub { + $meta_class->get_meta_instance + ->set_slot_value($_[0], $attr_name, $_[1]); + }; +} + +sub generate_predicate_method { + my $attr = (shift)->associated_attribute; + my $meta_class = $attr->associated_class; + my $attr_name = $attr->name; + return sub { + defined $meta_class->get_meta_instance + ->get_slot_value($_[0], $attr_name) ? 1 : 0; + }; +} package # hide the package from PAUSE InsideOutClass::Instance; @@ -6,7 +93,7 @@ package # hide the package from PAUSE use strict; use warnings; -our $VERSION = '0.06'; +our $VERSION = '0.01'; use Carp 'confess'; use Scalar::Util 'refaddr'; @@ -20,28 +107,27 @@ sub create_instance { sub get_slot_value { my ($self, $instance, $slot_name) = @_; - $self->{meta}->get_package_variable('%' . $slot_name)->{refaddr $instance}; + $self->associated_metaclass->get_package_symbol('%' . $slot_name)->{refaddr $instance}; } sub set_slot_value { my ($self, $instance, $slot_name, $value) = @_; - $self->{meta}->get_package_variable('%' . $slot_name)->{refaddr $instance} = $value; + $self->associated_metaclass->get_package_symbol('%' . $slot_name)->{refaddr $instance} = $value; } sub initialize_slot { my ($self, $instance, $slot_name) = @_; - $self->{meta}->add_package_variable('%' . $slot_name); - $self->{meta}->get_package_variable('%' . $slot_name)->{refaddr $instance} = undef; + $self->associated_metaclass->add_package_symbol(('%' . $slot_name) => {}) + unless $self->associated_metaclass->has_package_symbol('%' . $slot_name); + $self->associated_metaclass->get_package_symbol('%' . $slot_name)->{refaddr $instance} = undef; } sub is_slot_initialized { my ($self, $instance, $slot_name) = @_; - return 0 unless $self->{meta}->has_package_variable('%' . $slot_name); - return exists $self->{meta}->get_package_variable('%' . $slot_name)->{refaddr $instance} ? 1 : 0; + return 0 unless $self->associated_metaclass->has_package_symbol('%' . $slot_name); + return exists $self->associated_metaclass->get_package_symbol('%' . $slot_name)->{refaddr $instance} ? 1 : 0; } -## &remove_slot is left as an exercise for the reader :) - 1; __END__ @@ -56,11 +142,9 @@ InsideOutClass - A set of example metaclasses which implement the Inside-Out tec package Foo; - use metaclass 'Class::MOP::Class' => ( - # tell our metaclass to use the - # InsideOut attribute metclass - # to construct all it's attributes - ':instance_metaclass' => 'InsideOutClass::Instance' + use metaclass ( + ':attribute_metaclass' => 'InsideOutClass::Attribute', + ':instance_metaclass' => 'InsideOutClass::Instance' ); __PACKAGE__->meta->add_attribute('foo' => ( @@ -93,17 +177,15 @@ inside-out objects to be C-ed, and some other details as well (threading, etc), but this is an example. A real implementation is left as an exercise to the reader. -=head1 AUTHOR +=head1 AUTHORS Stevan Little Estevan@iinteractive.comE -=head1 SEE ALSO - -L +Yuval Kogman Enothingmuch@woobling.comE =head1 COPYRIGHT AND LICENSE -Copyright 2006 by Infinity Interactive, Inc. +Copyright 2006, 2007 by Infinity Interactive, Inc. L