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'});
49 return Class::MOP::Class->initialize($class)->new_object(@_)
50 if $class ne __PACKAGE__;
52 my $params = @_ == 1 ? $_[0] : {@_};
55 # I am not sure that it makes
56 # sense to pass in the meta
57 # The ideal would be to just
58 # pass in the class name, but
59 # that is placing too much of
60 # an assumption on bless(),
61 # which is *probably* a safe
62 # assumption,.. but you can
64 'associated_metaclass' => $params->{associated_metaclass},
65 'attributes' => $params->{attributes},
66 'slots' => $params->{slots},
67 'slot_hash' => $params->{slot_hash},
71 sub _class_name { $_[0]->{_class_name} ||= $_[0]->associated_metaclass->name }
73 sub associated_metaclass { $_[0]{'associated_metaclass'} }
77 bless {}, $self->_class_name;
81 sub bless_instance_structure {
82 Carp::cluck('The bless_instance_structure method is deprecated.'
83 . " It will be removed in a future release.\n");
85 my ($self, $instance_structure) = @_;
86 bless $instance_structure, $self->_class_name;
90 my ($self, $instance) = @_;
91 bless { %$instance }, $self->_class_name;
94 # operations on meta instance
98 return @{$self->{'slots'}};
101 sub get_all_attributes {
103 return @{$self->{attributes}};
107 my ($self, $slot_name) = @_;
108 exists $self->{'slot_hash'}->{$slot_name};
111 # operations on created instances
114 my ($self, $instance, $slot_name) = @_;
115 $instance->{$slot_name};
119 my ($self, $instance, $slot_name, $value) = @_;
120 $instance->{$slot_name} = $value;
123 sub initialize_slot {
124 my ($self, $instance, $slot_name) = @_;
128 sub deinitialize_slot {
129 my ( $self, $instance, $slot_name ) = @_;
130 delete $instance->{$slot_name};
133 sub initialize_all_slots {
134 my ($self, $instance) = @_;
135 foreach my $slot_name ($self->get_all_slots) {
136 $self->initialize_slot($instance, $slot_name);
140 sub deinitialize_all_slots {
141 my ($self, $instance) = @_;
142 foreach my $slot_name ($self->get_all_slots) {
143 $self->deinitialize_slot($instance, $slot_name);
147 sub is_slot_initialized {
148 my ($self, $instance, $slot_name, $value) = @_;
149 exists $instance->{$slot_name};
152 sub weaken_slot_value {
153 my ($self, $instance, $slot_name) = @_;
154 weaken $instance->{$slot_name};
157 sub strengthen_slot_value {
158 my ($self, $instance, $slot_name) = @_;
159 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
162 sub rebless_instance_structure {
163 my ($self, $instance, $metaclass) = @_;
165 # we use $_[1] here because of t/306_rebless_overload.t regressions on 5.8.8
166 bless $_[1], $metaclass->name;
169 sub is_dependent_on_superclasses {
170 return; # for meta instances that require updates on inherited slot changes
173 # inlinable operation snippets
175 sub is_inlinable { 1 }
177 sub inline_create_instance {
178 my ($self, $class_variable) = @_;
179 'bless {} => ' . $class_variable;
182 sub inline_slot_access {
183 my ($self, $instance, $slot_name) = @_;
184 sprintf q[%s->{'%s'}], $instance, quotemeta($slot_name);
187 sub inline_get_slot_value {
188 my ($self, $instance, $slot_name) = @_;
189 $self->inline_slot_access($instance, $slot_name);
192 sub inline_set_slot_value {
193 my ($self, $instance, $slot_name, $value) = @_;
194 $self->inline_slot_access($instance, $slot_name) . " = $value",
197 sub inline_initialize_slot {
198 my ($self, $instance, $slot_name) = @_;
202 sub inline_deinitialize_slot {
203 my ($self, $instance, $slot_name) = @_;
204 "delete " . $self->inline_slot_access($instance, $slot_name);
206 sub inline_is_slot_initialized {
207 my ($self, $instance, $slot_name) = @_;
208 "exists " . $self->inline_slot_access($instance, $slot_name);
211 sub inline_weaken_slot_value {
212 my ($self, $instance, $slot_name) = @_;
213 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
216 sub inline_strengthen_slot_value {
217 my ($self, $instance, $slot_name) = @_;
218 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
221 sub inline_rebless_instance_structure {
222 my ($self, $instance, $class_variable) = @_;
223 "bless $instance => $class_variable";
234 Class::MOP::Instance - Instance Meta Object
238 The Instance Protocol controls the creation of object instances, and
239 the storage of attribute values in those instances.
241 Using this API directly in your own code violates encapsulation, and
242 we recommend that you use the appropriate APIs in L<Class::MOP::Class>
243 and L<Class::MOP::Attribute> instead. Those APIs in turn call the
244 methods in this class as appropriate.
246 This class also participates in generating inlined code by providing
247 snippets of code to access an object instance.
251 =head2 Object construction
255 =item B<< Class::MOP::Instance->new(%options) >>
257 This method creates a new meta-instance object.
259 It accepts the following keys in C<%options>:
263 =item * associated_metaclass
265 The L<Class::MOP::Class> object for which instances will be created.
269 An array reference of L<Class::MOP::Attribute> objects. These are the
270 attributes which can be stored in each instance.
276 =head2 Creating and altering instances
280 =item B<< $metainstance->create_instance >>
282 This method returns a reference blessed into the associated
285 The default is to use a hash reference. Subclasses can override this.
287 =item B<< $metainstance->clone_instance($instance) >>
289 Given an instance, this method creates a new object by making
290 I<shallow> clone of the original.
298 =item B<< $metainstance->associated_metaclass >>
300 This returns the L<Class::MOP::Class> object associated with the
301 meta-instance object.
303 =item B<< $metainstance->get_all_slots >>
305 This returns a list of slot names stored in object instances. In
306 almost all cases, slot names correspond directly attribute names.
308 =item B<< $metainstance->is_valid_slot($slot_name) >>
310 This will return true if C<$slot_name> is a valid slot name.
312 =item B<< $metainstance->get_all_attributes >>
314 This returns a list of attributes corresponding to the attributes
315 passed to the constructor.
319 =head2 Operations on Instance Structures
321 It's important to understand that the meta-instance object is a
322 different entity from the actual instances it creates. For this
323 reason, any operations on the C<$instance_structure> always require
324 that the object instance be passed to the method.
328 =item B<< $metainstance->get_slot_value($instance_structure, $slot_name) >>
330 =item B<< $metainstance->set_slot_value($instance_structure, $slot_name, $value) >>
332 =item B<< $metainstance->initialize_slot($instance_structure, $slot_name) >>
334 =item B<< $metainstance->deinitialize_slot($instance_structure, $slot_name) >>
336 =item B<< $metainstance->initialize_all_slots($instance_structure) >>
338 =item B<< $metainstance->deinitialize_all_slots($instance_structure) >>
340 =item B<< $metainstance->is_slot_initialized($instance_structure, $slot_name) >>
342 =item B<< $metainstance->weaken_slot_value($instance_structure, $slot_name) >>
344 =item B<< $metainstance->strengthen_slot_value($instance_structure, $slot_name) >>
346 =item B<< $metainstance->rebless_instance_structure($instance_structure, $new_metaclass) >>
348 The exact details of what each method does should be fairly obvious
349 from the method name.
353 =head2 Inlinable Instance Operations
357 =item B<< $metainstance->is_inlinable >>
359 This is a boolean that indicates whether or not slot access operations
360 can be inlined. By default it is true, but subclasses can override
363 =item B<< $metainstance->inline_create_instance($class_variable) >>
365 This method expects a string that, I<when inlined>, will become a
366 class name. This would literally be something like C<'$class'>, not an
369 It returns a snippet of code that creates a new object for the
370 class. This is something like C< bless {}, $class_name >.
372 =item B<< $metainstance->inline_slot_access($instance_variable, $slot_name) >>
374 =item B<< $metainstance->inline_get_slot_value($instance_variable, $slot_name) >>
376 =item B<< $metainstance->inline_set_slot_value($instance_variable, $slot_name, $value) >>
378 =item B<< $metainstance->inline_initialize_slot($instance_variable, $slot_name) >>
380 =item B<< $metainstance->inline_deinitialize_slot($instance_variable, $slot_name) >>
382 =item B<< $metainstance->inline_is_slot_initialized($instance_variable, $slot_name) >>
384 =item B<< $metainstance->inline_weaken_slot_value($instance_variable, $slot_name) >>
386 =item B<< $metainstance->inline_strengthen_slot_value($instance_variable, $slot_name) >>
388 These methods all expect two arguments. The first is the name of a
389 variable, than when inlined, will represent the object
390 instance. Typically this will be a literal string like C<'$_[0]'>.
392 The second argument is a slot name.
394 The method returns a snippet of code that, when inlined, performs some
395 operation on the instance.
397 =item B<< $metainstance->inline_rebless_instance_structure($instance_variable, $class_variable) >>
399 This takes the name of a variable that will, when inlined, represent the object
400 instance, and the name of a variable that will represent the class to rebless
401 into, and returns code to rebless an instance into a class.
409 =item B<< Class::MOP::Instance->meta >>
411 This will return a L<Class::MOP::Class> instance for this class.
413 It should also be noted that L<Class::MOP> will actually bootstrap
414 this module by installing a number of attribute meta-objects into its
421 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
423 Stevan Little E<lt>stevan@iinteractive.comE<gt>
425 =head1 COPYRIGHT AND LICENSE
427 Copyright 2006-2009 by Infinity Interactive, Inc.
429 L<http://www.iinteractive.com>
431 This library is free software; you can redistribute it and/or modify
432 it under the same terms as Perl itself.