2 package Class::MOP::Instance;
7 use Scalar::Util 'weaken', 'blessed';
9 use base 'Class::MOP::Object';
11 # make this not a valid method name, to avoid (most) attribute conflicts
12 my $RESERVED_MOP_SLOT = '<<MOP>>';
15 my ($class, @args) = @_;
18 unshift @args, "associated_metaclass";
19 } elsif ( @args >= 2 && blessed($args[0]) && $args[0]->isa("Class::MOP::Class") ) {
21 my ( $meta, @attrs ) = @args;
22 @args = ( associated_metaclass => $meta, attributes => \@attrs );
27 $options{slots} ||= [ map { $_->slots } @{ $options{attributes} || [] } ];
28 $options{slot_hash} = { map { $_ => undef } @{ $options{slots} } }; # FIXME lazy_build
35 my $options = $class->BUILDARGS(@_);
37 # FIXME replace with a proper constructor
38 my $instance = $class->_new(%$options);
40 # FIXME weak_ref => 1,
41 weaken($instance->{'associated_metaclass'});
48 return Class::MOP::Class->initialize($class)->new_object(@_)
49 if $class ne __PACKAGE__;
51 my $params = @_ == 1 ? $_[0] : {@_};
54 # I am not sure that it makes
55 # sense to pass in the meta
56 # The ideal would be to just
57 # pass in the class name, but
58 # that is placing too much of
59 # an assumption on bless(),
60 # which is *probably* a safe
61 # assumption,.. but you can
63 'associated_metaclass' => $params->{associated_metaclass},
64 'attributes' => $params->{attributes},
65 'slots' => $params->{slots},
66 'slot_hash' => $params->{slot_hash},
70 sub _class_name { $_[0]->{_class_name} ||= $_[0]->associated_metaclass->name }
74 bless {}, $self->_class_name;
78 my ($self, $instance) = @_;
80 my $clone = bless {}, $self->_class_name;
81 for my $attr ($self->get_all_attributes) {
82 $attr->set_value($clone, $attr->get_raw_value($instance))
83 if $attr->has_value($instance);
89 # operations on meta instance
93 return @{$self->{'slots'}};
96 sub get_all_attributes {
98 return @{$self->{attributes}};
102 my ($self, $slot_name) = @_;
103 exists $self->{'slot_hash'}->{$slot_name};
106 # operations on created instances
109 my ($self, $instance, $slot_name) = @_;
110 $instance->{$slot_name};
114 my ($self, $instance, $slot_name, $value) = @_;
115 $instance->{$slot_name} = $value;
118 sub initialize_slot {
119 my ($self, $instance, $slot_name) = @_;
123 sub deinitialize_slot {
124 my ( $self, $instance, $slot_name ) = @_;
125 delete $instance->{$slot_name};
128 sub initialize_all_slots {
129 my ($self, $instance) = @_;
130 foreach my $slot_name ($self->get_all_slots) {
131 $self->initialize_slot($instance, $slot_name);
135 sub deinitialize_all_slots {
136 my ($self, $instance) = @_;
137 foreach my $slot_name ($self->get_all_slots) {
138 $self->deinitialize_slot($instance, $slot_name);
142 sub is_slot_initialized {
143 my ($self, $instance, $slot_name, $value) = @_;
144 exists $instance->{$slot_name};
147 sub weaken_slot_value {
148 my ($self, $instance, $slot_name) = @_;
149 weaken $instance->{$slot_name};
152 sub strengthen_slot_value {
153 my ($self, $instance, $slot_name) = @_;
154 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
157 sub rebless_instance_structure {
158 my ($self, $instance, $metaclass) = @_;
160 # we use $_[1] here because of t/cmop/rebless_overload.t regressions
162 bless $_[1], $metaclass->name;
165 sub is_dependent_on_superclasses {
166 return; # for meta instances that require updates on inherited slot changes
170 my ($self, $instance) = @_;
171 $self->get_slot_value($instance, $RESERVED_MOP_SLOT);
175 my ($self, $instance, $value) = @_;
176 $self->set_slot_value($instance, $RESERVED_MOP_SLOT, $value);
179 sub _clear_mop_slot {
180 my ($self, $instance) = @_;
181 $self->deinitialize_slot($instance, $RESERVED_MOP_SLOT);
184 # inlinable operation snippets
186 sub is_inlinable { 1 }
188 sub inline_create_instance {
189 my ($self, $class_variable) = @_;
190 'bless {} => ' . $class_variable;
193 sub inline_slot_access {
194 my ($self, $instance, $slot_name) = @_;
195 sprintf q[%s->{"%s"}], $instance, quotemeta($slot_name);
198 sub inline_get_is_lvalue { 1 }
200 sub inline_get_slot_value {
201 my ($self, $instance, $slot_name) = @_;
202 $self->inline_slot_access($instance, $slot_name);
205 sub inline_set_slot_value {
206 my ($self, $instance, $slot_name, $value) = @_;
207 $self->inline_slot_access($instance, $slot_name) . " = $value",
210 sub inline_initialize_slot {
211 my ($self, $instance, $slot_name) = @_;
215 sub inline_deinitialize_slot {
216 my ($self, $instance, $slot_name) = @_;
217 "delete " . $self->inline_slot_access($instance, $slot_name);
219 sub inline_is_slot_initialized {
220 my ($self, $instance, $slot_name) = @_;
221 "exists " . $self->inline_slot_access($instance, $slot_name);
224 sub inline_weaken_slot_value {
225 my ($self, $instance, $slot_name) = @_;
226 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
229 sub inline_strengthen_slot_value {
230 my ($self, $instance, $slot_name) = @_;
231 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
234 sub inline_rebless_instance_structure {
235 my ($self, $instance, $class_variable) = @_;
236 "bless $instance => $class_variable";
239 sub _inline_get_mop_slot {
240 my ($self, $instance) = @_;
241 $self->inline_get_slot_value($instance, $RESERVED_MOP_SLOT);
244 sub _inline_set_mop_slot {
245 my ($self, $instance, $value) = @_;
246 $self->inline_set_slot_value($instance, $RESERVED_MOP_SLOT, $value);
249 sub _inline_clear_mop_slot {
250 my ($self, $instance) = @_;
251 $self->inline_deinitialize_slot($instance, $RESERVED_MOP_SLOT);
256 # ABSTRACT: Instance Meta Object
264 The Instance Protocol controls the creation of object instances, and
265 the storage of attribute values in those instances.
267 Using this API directly in your own code violates encapsulation, and
268 we recommend that you use the appropriate APIs in L<Class::MOP::Class>
269 and L<Class::MOP::Attribute> instead. Those APIs in turn call the
270 methods in this class as appropriate.
272 This class also participates in generating inlined code by providing
273 snippets of code to access an object instance.
277 =head2 Object construction
281 =item B<< Class::MOP::Instance->new(%options) >>
283 This method creates a new meta-instance object.
285 It accepts the following keys in C<%options>:
289 =item * associated_metaclass
291 The L<Class::MOP::Class> object for which instances will be created.
295 An array reference of L<Class::MOP::Attribute> objects. These are the
296 attributes which can be stored in each instance.
302 =head2 Creating and altering instances
306 =item B<< $metainstance->create_instance >>
308 This method returns a reference blessed into the associated
311 The default is to use a hash reference. Subclasses can override this.
313 =item B<< $metainstance->clone_instance($instance) >>
315 Given an instance, this method creates a new object by making
316 I<shallow> clone of the original.
324 =item B<< $metainstance->associated_metaclass >>
326 This returns the L<Class::MOP::Class> object associated with the
327 meta-instance object.
329 =item B<< $metainstance->get_all_slots >>
331 This returns a list of slot names stored in object instances. In
332 almost all cases, slot names correspond directly attribute names.
334 =item B<< $metainstance->is_valid_slot($slot_name) >>
336 This will return true if C<$slot_name> is a valid slot name.
338 =item B<< $metainstance->get_all_attributes >>
340 This returns a list of attributes corresponding to the attributes
341 passed to the constructor.
345 =head2 Operations on Instance Structures
347 It's important to understand that the meta-instance object is a
348 different entity from the actual instances it creates. For this
349 reason, any operations on the C<$instance_structure> always require
350 that the object instance be passed to the method.
354 =item B<< $metainstance->get_slot_value($instance_structure, $slot_name) >>
356 =item B<< $metainstance->set_slot_value($instance_structure, $slot_name, $value) >>
358 =item B<< $metainstance->initialize_slot($instance_structure, $slot_name) >>
360 =item B<< $metainstance->deinitialize_slot($instance_structure, $slot_name) >>
362 =item B<< $metainstance->initialize_all_slots($instance_structure) >>
364 =item B<< $metainstance->deinitialize_all_slots($instance_structure) >>
366 =item B<< $metainstance->is_slot_initialized($instance_structure, $slot_name) >>
368 =item B<< $metainstance->weaken_slot_value($instance_structure, $slot_name) >>
370 =item B<< $metainstance->strengthen_slot_value($instance_structure, $slot_name) >>
372 =item B<< $metainstance->rebless_instance_structure($instance_structure, $new_metaclass) >>
374 The exact details of what each method does should be fairly obvious
375 from the method name.
379 =head2 Inlinable Instance Operations
383 =item B<< $metainstance->is_inlinable >>
385 This is a boolean that indicates whether or not slot access operations
386 can be inlined. By default it is true, but subclasses can override
389 =item B<< $metainstance->inline_create_instance($class_variable) >>
391 This method expects a string that, I<when inlined>, will become a
392 class name. This would literally be something like C<'$class'>, not an
395 It returns a snippet of code that creates a new object for the
396 class. This is something like C< bless {}, $class_name >.
398 =item B<< $metainstance->inline_get_is_lvalue >>
400 Returns whether or not C<inline_get_slot_value> is a valid lvalue. This can be
401 used to do extra optimizations when generating inlined methods.
403 =item B<< $metainstance->inline_slot_access($instance_variable, $slot_name) >>
405 =item B<< $metainstance->inline_get_slot_value($instance_variable, $slot_name) >>
407 =item B<< $metainstance->inline_set_slot_value($instance_variable, $slot_name, $value) >>
409 =item B<< $metainstance->inline_initialize_slot($instance_variable, $slot_name) >>
411 =item B<< $metainstance->inline_deinitialize_slot($instance_variable, $slot_name) >>
413 =item B<< $metainstance->inline_is_slot_initialized($instance_variable, $slot_name) >>
415 =item B<< $metainstance->inline_weaken_slot_value($instance_variable, $slot_name) >>
417 =item B<< $metainstance->inline_strengthen_slot_value($instance_variable, $slot_name) >>
419 These methods all expect two arguments. The first is the name of a
420 variable, than when inlined, will represent the object
421 instance. Typically this will be a literal string like C<'$_[0]'>.
423 The second argument is a slot name.
425 The method returns a snippet of code that, when inlined, performs some
426 operation on the instance.
428 =item B<< $metainstance->inline_rebless_instance_structure($instance_variable, $class_variable) >>
430 This takes the name of a variable that will, when inlined, represent the object
431 instance, and the name of a variable that will represent the class to rebless
432 into, and returns code to rebless an instance into a class.
440 =item B<< Class::MOP::Instance->meta >>
442 This will return a L<Class::MOP::Class> instance for this class.
444 It should also be noted that L<Class::MOP> will actually bootstrap
445 this module by installing a number of attribute meta-objects into its