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 $slot_name =~ s/(['\\])/\\$1/g; # In '', only "'" and "\\" are meta characters.
185 sprintf q[%s->{'%s'}], $instance, $slot_name;
188 sub inline_get_slot_value {
189 my ($self, $instance, $slot_name) = @_;
190 $self->inline_slot_access($instance, $slot_name);
193 sub inline_set_slot_value {
194 my ($self, $instance, $slot_name, $value) = @_;
195 $self->inline_slot_access($instance, $slot_name) . " = $value",
198 sub inline_initialize_slot {
199 my ($self, $instance, $slot_name) = @_;
203 sub inline_deinitialize_slot {
204 my ($self, $instance, $slot_name) = @_;
205 "delete " . $self->inline_slot_access($instance, $slot_name);
207 sub inline_is_slot_initialized {
208 my ($self, $instance, $slot_name) = @_;
209 "exists " . $self->inline_slot_access($instance, $slot_name);
212 sub inline_weaken_slot_value {
213 my ($self, $instance, $slot_name) = @_;
214 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
217 sub inline_strengthen_slot_value {
218 my ($self, $instance, $slot_name) = @_;
219 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
222 sub inline_rebless_instance_structure {
223 my ($self, $instance, $class_variable) = @_;
224 "bless $instance => $class_variable";
235 Class::MOP::Instance - Instance Meta Object
239 The Instance Protocol controls the creation of object instances, and
240 the storage of attribute values in those instances.
242 Using this API directly in your own code violates encapsulation, and
243 we recommend that you use the appropriate APIs in L<Class::MOP::Class>
244 and L<Class::MOP::Attribute> instead. Those APIs in turn call the
245 methods in this class as appropriate.
247 This class also participates in generating inlined code by providing
248 snippets of code to access an object instance.
252 =head2 Object construction
256 =item B<< Class::MOP::Instance->new(%options) >>
258 This method creates a new meta-instance object.
260 It accepts the following keys in C<%options>:
264 =item * associated_metaclass
266 The L<Class::MOP::Class> object for which instances will be created.
270 An array reference of L<Class::MOP::Attribute> objects. These are the
271 attributes which can be stored in each instance.
277 =head2 Creating and altering instances
281 =item B<< $metainstance->create_instance >>
283 This method returns a reference blessed into the associated
286 The default is to use a hash reference. Subclasses can override this.
288 =item B<< $metainstance->clone_instance($instance) >>
290 Given an instance, this method creates a new object by making
291 I<shallow> clone of the original.
299 =item B<< $metainstance->associated_metaclass >>
301 This returns the L<Class::MOP::Class> object associated with the
302 meta-instance object.
304 =item B<< $metainstance->get_all_slots >>
306 This returns a list of slot names stored in object instances. In
307 almost all cases, slot names correspond directly attribute names.
309 =item B<< $metainstance->is_valid_slot($slot_name) >>
311 This will return true if C<$slot_name> is a valid slot name.
313 =item B<< $metainstance->get_all_attributes >>
315 This returns a list of attributes corresponding to the attributes
316 passed to the constructor.
320 =head2 Operations on Instance Structures
322 It's important to understand that the meta-instance object is a
323 different entity from the actual instances it creates. For this
324 reason, any operations on the C<$instance_structure> always require
325 that the object instance be passed to the method.
329 =item B<< $metainstance->get_slot_value($instance_structure, $slot_name) >>
331 =item B<< $metainstance->set_slot_value($instance_structure, $slot_name, $value) >>
333 =item B<< $metainstance->initialize_slot($instance_structure, $slot_name) >>
335 =item B<< $metainstance->deinitialize_slot($instance_structure, $slot_name) >>
337 =item B<< $metainstance->initialize_all_slots($instance_structure) >>
339 =item B<< $metainstance->deinitialize_all_slots($instance_structure) >>
341 =item B<< $metainstance->is_slot_initialized($instance_structure, $slot_name) >>
343 =item B<< $metainstance->weaken_slot_value($instance_structure, $slot_name) >>
345 =item B<< $metainstance->strengthen_slot_value($instance_structure, $slot_name) >>
347 =item B<< $metainstance->rebless_instance_structure($instance_structure, $new_metaclass) >>
349 The exact details of what each method does should be fairly obvious
350 from the method name.
354 =head2 Inlinable Instance Operations
358 =item B<< $metainstance->is_inlinable >>
360 This is a boolean that indicates whether or not slot access operations
361 can be inlined. By default it is true, but subclasses can override
364 =item B<< $metainstance->inline_create_instance($class_variable) >>
366 This method expects a string that, I<when inlined>, will become a
367 class name. This would literally be something like C<'$class'>, not an
370 It returns a snippet of code that creates a new object for the
371 class. This is something like C< bless {}, $class_name >.
373 =item B<< $metainstance->inline_slot_access($instance_variable, $slot_name) >>
375 =item B<< $metainstance->inline_get_slot_value($instance_variable, $slot_name) >>
377 =item B<< $metainstance->inline_set_slot_value($instance_variable, $slot_name, $value) >>
379 =item B<< $metainstance->inline_initialize_slot($instance_variable, $slot_name) >>
381 =item B<< $metainstance->inline_deinitialize_slot($instance_variable, $slot_name) >>
383 =item B<< $metainstance->inline_is_slot_initialized($instance_variable, $slot_name) >>
385 =item B<< $metainstance->inline_weaken_slot_value($instance_variable, $slot_name) >>
387 =item B<< $metainstance->inline_strengthen_slot_value($instance_variable, $slot_name) >>
389 These methods all expect two arguments. The first is the name of a
390 variable, than when inlined, will represent the object
391 instance. Typically this will be a literal string like C<'$_[0]'>.
393 The second argument is a slot name.
395 The method returns a snippet of code that, when inlined, performs some
396 operation on the instance.
398 =item B<< $metainstance->inline_rebless_instance_structure($instance_variable, $class_variable) >>
400 This takes the name of a variable that will, when inlined, represent the object
401 instance, and the name of a variable that will represent the class to rebless
402 into, and returns code to rebless an instance into a class.
410 =item B<< Class::MOP::Instance->meta >>
412 This will return a L<Class::MOP::Class> instance for this class.
414 It should also be noted that L<Class::MOP> will actually bootstrap
415 this module by installing a number of attribute meta-objects into its
422 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
424 Stevan Little E<lt>stevan@iinteractive.comE<gt>
426 =head1 COPYRIGHT AND LICENSE
428 Copyright 2006-2009 by Infinity Interactive, Inc.
430 L<http://www.iinteractive.com>
432 This library is free software; you can redistribute it and/or modify
433 it under the same terms as Perl itself.