2 package Class::MOP::Instance;
7 use Scalar::Util 'weaken', 'blessed';
10 $VERSION = eval $VERSION;
11 our $AUTHORITY = 'cpan:STEVAN';
13 use base 'Class::MOP::Object';
16 my ($class, @args) = @_;
19 unshift @args, "associated_metaclass";
20 } elsif ( @args >= 2 && blessed($args[0]) && $args[0]->isa("Class::MOP::Class") ) {
22 my ( $meta, @attrs ) = @args;
23 @args = ( associated_metaclass => $meta, attributes => \@attrs );
28 $options{slots} ||= [ map { $_->slots } @{ $options{attributes} || [] } ];
29 $options{slot_hash} = { map { $_ => undef } @{ $options{slots} } }; # FIXME lazy_build
36 my $options = $class->BUILDARGS(@_);
38 # FIXME replace with a proper constructor
39 my $instance = $class->_new(%$options);
41 # FIXME weak_ref => 1,
42 weaken($instance->{'associated_metaclass'});
48 my ( $class, %options ) = @_;
51 # I am not sure that it makes
52 # sense to pass in the meta
53 # The ideal would be to just
54 # pass in the class name, but
55 # that is placing too much of
56 # an assumption on bless(),
57 # which is *probably* a safe
58 # assumption,.. but you can
60 'associated_metaclass' => $options{associated_metaclass},
61 'attributes' => $options{attributes},
62 'slots' => $options{slots},
63 'slot_hash' => $options{slot_hash},
67 sub _class_name { $_[0]->{_class_name} ||= $_[0]->associated_metaclass->name }
69 sub associated_metaclass { $_[0]{'associated_metaclass'} }
73 bless {}, $self->_class_name;
77 sub bless_instance_structure {
78 Carp::cluck('The bless_instance_structure method is deprecated.'
79 . " It will be removed in a future release.\n");
81 my ($self, $instance_structure) = @_;
82 bless $instance_structure, $self->_class_name;
86 my ($self, $instance) = @_;
87 bless { %$instance }, $self->_class_name;
90 # operations on meta instance
94 return @{$self->{'slots'}};
97 sub get_all_attributes {
99 return @{$self->{attributes}};
103 my ($self, $slot_name) = @_;
104 exists $self->{'slot_hash'}->{$slot_name};
107 # operations on created instances
110 my ($self, $instance, $slot_name) = @_;
111 $instance->{$slot_name};
115 my ($self, $instance, $slot_name, $value) = @_;
116 $instance->{$slot_name} = $value;
119 sub initialize_slot {
120 my ($self, $instance, $slot_name) = @_;
124 sub deinitialize_slot {
125 my ( $self, $instance, $slot_name ) = @_;
126 delete $instance->{$slot_name};
129 sub initialize_all_slots {
130 my ($self, $instance) = @_;
131 foreach my $slot_name ($self->get_all_slots) {
132 $self->initialize_slot($instance, $slot_name);
136 sub deinitialize_all_slots {
137 my ($self, $instance) = @_;
138 foreach my $slot_name ($self->get_all_slots) {
139 $self->deinitialize_slot($instance, $slot_name);
143 sub is_slot_initialized {
144 my ($self, $instance, $slot_name, $value) = @_;
145 exists $instance->{$slot_name};
148 sub weaken_slot_value {
149 my ($self, $instance, $slot_name) = @_;
150 weaken $instance->{$slot_name};
153 sub strengthen_slot_value {
154 my ($self, $instance, $slot_name) = @_;
155 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
158 sub rebless_instance_structure {
159 my ($self, $instance, $metaclass) = @_;
161 # we use $_[1] here because of t/306_rebless_overload.t regressions on 5.8.8
162 bless $_[1], $metaclass->name;
165 sub is_dependent_on_superclasses {
166 return; # for meta instances that require updates on inherited slot changes
169 # inlinable operation snippets
171 sub is_inlinable { 1 }
173 sub inline_create_instance {
174 my ($self, $class_variable) = @_;
175 'bless {} => ' . $class_variable;
178 sub inline_slot_access {
179 my ($self, $instance, $slot_name) = @_;
180 sprintf q[%s->{"%s"}], $instance, quotemeta($slot_name);
183 sub inline_get_slot_value {
184 my ($self, $instance, $slot_name) = @_;
185 $self->inline_slot_access($instance, $slot_name);
188 sub inline_set_slot_value {
189 my ($self, $instance, $slot_name, $value) = @_;
190 $self->inline_slot_access($instance, $slot_name) . " = $value",
193 sub inline_initialize_slot {
194 my ($self, $instance, $slot_name) = @_;
198 sub inline_deinitialize_slot {
199 my ($self, $instance, $slot_name) = @_;
200 "delete " . $self->inline_slot_access($instance, $slot_name);
202 sub inline_is_slot_initialized {
203 my ($self, $instance, $slot_name) = @_;
204 "exists " . $self->inline_slot_access($instance, $slot_name);
207 sub inline_weaken_slot_value {
208 my ($self, $instance, $slot_name) = @_;
209 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
212 sub inline_strengthen_slot_value {
213 my ($self, $instance, $slot_name) = @_;
214 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
225 Class::MOP::Instance - Instance Meta Object
229 The Instance Protocol controls the creation of object instances, and
230 the storage of attribute values in those instances.
232 Using this API directly in your own code violates encapsulation, and
233 we recommend that you use the appropriate APIs in L<Class::MOP::Class>
234 and L<Class::MOP::Attribute> instead. Those APIs in turn call the
235 methods in this class as appropriate.
237 This class also participates in generating inlined code by providing
238 snippets of code to access an object instance.
242 =head2 Object construction
246 =item B<< Class::MOP::Instance->new(%options) >>
248 This method creates a new meta-instance object.
250 It accepts the following keys in C<%options>:
254 =item * associated_metaclass
256 The L<Class::MOP::Class> object for which instances will be created.
260 An array reference of L<Class::MOP::Attribute> objects. These are the
261 attributes which can be stored in each instance.
267 =head2 Creating and altering instances
271 =item B<< $metainstance->create_instance >>
273 This method returns a reference blessed into the associated
276 The default is to use a hash reference. Subclasses can override this.
278 =item B<< $metainstance->clone_instance($instance) >>
280 Given an instance, this method creates a new object by making
281 I<shallow> clone of the original.
289 =item B<< $metainstance->associated_metaclass >>
291 This returns the L<Class::MOP::Class> object associated with the
292 meta-instance object.
294 =item B<< $metainstance->get_all_slots >>
296 This returns a list of slot names stored in object instances. In
297 almost all cases, slot names correspond directly attribute names.
299 =item B<< $metainstance->is_valid_slot($slot_name) >>
301 This will return true if C<$slot_name> is a valid slot name.
303 =item B<< $metainstance->get_all_attributes >>
305 This returns a list of attributes corresponding to the attributes
306 passed to the constructor.
310 =head2 Operations on Instance Structures
312 It's important to understand that the meta-instance object is a
313 different entity from the actual instances it creates. For this
314 reason, any operations on the C<$instance_structure> always require
315 that the object instance be passed to the method.
319 =item B<< $metainstance->get_slot_value($instance_structure, $slot_name) >>
321 =item B<< $metainstance->set_slot_value($instance_structure, $slot_name, $value) >>
323 =item B<< $metainstance->initialize_slot($instance_structure, $slot_name) >>
325 =item B<< $metainstance->deinitialize_slot($instance_structure, $slot_name) >>
327 =item B<< $metainstance->initialize_all_slots($instance_structure) >>
329 =item B<< $metainstance->deinitialize_all_slots($instance_structure) >>
331 =item B<< $metainstance->is_slot_initialized($instance_structure, $slot_name) >>
333 =item B<< $metainstance->weaken_slot_value($instance_structure, $slot_name) >>
335 =item B<< $metainstance->strengthen_slot_value($instance_structure, $slot_name) >>
337 =item B<< $metainstance->rebless_instance_structure($instance_structure, $new_metaclass) >>
339 The exact details of what each method does should be fairly obvious
340 from the method name.
344 =head2 Inlinable Instance Operations
348 =item B<< $metainstance->is_inlinable >>
350 This is a boolean that indicates whether or not slot access operations
351 can be inlined. By default it is true, but subclasses can override
354 =item B<< $metainstance->inline_create_instance($class_variable) >>
356 This method expects a string that, I<when inlined>, will become a
357 class name. This would literally be something like C<'$class'>, not an
360 It returns a snippet of code that creates a new object for the
361 class. This is something like C< bless {}, $class_name >.
363 =item B<< $metainstance->inline_slot_access($instance_variable, $slot_name) >>
365 =item B<< $metainstance->inline_get_slot_value($instance_variable, $slot_name) >>
367 =item B<< $metainstance->inline_set_slot_value($instance_variable, $slot_name, $value) >>
369 =item B<< $metainstance->inline_initialize_slot($instance_variable, $slot_name) >>
371 =item B<< $metainstance->inline_deinitialize_slot($instance_variable, $slot_name) >>
373 =item B<< $metainstance->inline_is_slot_initialized($instance_variable, $slot_name) >>
375 =item B<< $metainstance->inline_weaken_slot_value($instance_variable, $slot_name) >>
377 =item B<< $metainstance->inline_strengthen_slot_value($instance_variable, $slot_name) >>
379 These methods all expect two arguments. The first is the name of a
380 variable, than when inlined, will represent the object
381 instance. Typically this will be a literal string like C<'$_[0]'>.
383 The second argument is a slot name.
385 The method returns a snippet of code that, when inlined, performs some
386 operation on the instance.
394 =item B<< Class::MOP::Instance->meta >>
396 This will return a L<Class::MOP::Class> instance for this class.
398 It should also be noted that L<Class::MOP> will actually bootstrap
399 this module by installing a number of attribute meta-objects into its
406 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
408 Stevan Little E<lt>stevan@iinteractive.comE<gt>
410 =head1 COPYRIGHT AND LICENSE
412 Copyright 2006-2009 by Infinity Interactive, Inc.
414 L<http://www.iinteractive.com>
416 This library is free software; you can redistribute it and/or modify
417 it under the same terms as Perl itself.