File Coverage

blib/lib/Class/MOP/Instance.pm
Criterion Covered Total %
statement 104 116 89.6
branch 12 16 75.0
condition 5 11 45.4
subroutine 40 44 90.9
pod 29 31 93.5
total 190 218 87.1


line stmt bran cond sub pod time code
1             package Class::MOP::Instance;
2             our $VERSION = '2.2206';
3              
4 451     451   137814 use strict;
  451         942  
  451         13184  
5 451     451   2376 use warnings;
  451         952  
  451         13234  
6              
7 451     451   2515 use Scalar::Util 'isweak', 'weaken', 'blessed';
  451         1054  
  451         24988  
8              
9 451     451   3906 use parent 'Class::MOP::Object';
  451         1783  
  451         2802  
10              
11             # make this not a valid method name, to avoid (most) attribute conflicts
12             my $RESERVED_MOP_SLOT = '<<MOP>>';
13              
14             sub BUILDARGS {
15 21139     21139 0 56589 my ($class, @args) = @_;
16              
17 21139 50 33     142229 if ( @args == 1 ) {
    50 33        
18 0         0 unshift @args, "associated_metaclass";
19             } elsif ( @args >= 2 && blessed($args[0]) && $args[0]->isa("Class::MOP::Class") ) {
20             # compat mode
21 0         0 my ( $meta, @attrs ) = @args;
22 0         0 @args = ( associated_metaclass => $meta, attributes => \@attrs );
23             }
24              
25 21139         68698 my %options = @args;
26             # FIXME lazy_build
27 21139 50 50     72539 $options{slots} ||= [ map { $_->slots } @{ $options{attributes} || [] } ];
  172007         313657  
  21139         59528  
28 21139         41826 $options{slot_hash} = { map { $_ => undef } @{ $options{slots} } }; # FIXME lazy_build
  172008         330783  
  21139         44813  
29              
30 21139         68904 return \%options;
31             }
32              
33             sub new {
34 21139     21139 1 42409 my $class = shift;
35 21139         56220 my $options = $class->BUILDARGS(@_);
36              
37             # FIXME replace with a proper constructor
38 21139         168884 my $instance = $class->_new(%$options);
39              
40             # FIXME weak_ref => 1,
41 21139         91192 weaken($instance->{'associated_metaclass'});
42              
43 21139         64905 return $instance;
44             }
45              
46             sub _new {
47 18552     18552   31720 my $class = shift;
48 18552 100       43614 return Class::MOP::Class->initialize($class)->new_object(@_)
49             if $class ne __PACKAGE__;
50              
51 18541 50       64755 my $params = @_ == 1 ? $_[0] : {@_};
52             return bless {
53             # NOTE:
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
62             # never tell <:)
63             'associated_metaclass' => $params->{associated_metaclass},
64             'attributes' => $params->{attributes},
65             'slots' => $params->{slots},
66             'slot_hash' => $params->{slot_hash},
67 18541         93180 } => $class;
68             }
69              
70 23595   66 23595   109654 sub _class_name { $_[0]->{_class_name} ||= $_[0]->associated_metaclass->name }
71              
72             sub create_instance {
73 23584     23584 1 39360 my $self = shift;
74 23584         57251 bless {}, $self->_class_name;
75             }
76              
77             sub clone_instance {
78 17     17 1 47 my ($self, $instance) = @_;
79              
80 17         46 my $clone = $self->create_instance;
81 17         71 for my $attr ($self->get_all_attributes) {
82 172 100       384 next unless $attr->has_value($instance);
83 162         363 for my $slot ($attr->slots) {
84 163         411 my $val = $self->get_slot_value($instance, $slot);
85 163         351 $self->set_slot_value($clone, $slot, $val);
86 163 100       304 $self->weaken_slot_value($clone, $slot)
87             if $self->slot_value_is_weak($instance, $slot);
88             }
89             }
90              
91 17 100       92 $self->_set_mop_slot($clone, $self->_get_mop_slot($instance))
92             if $self->_has_mop_slot($instance);
93              
94 17         62 return $clone;
95             }
96              
97             # operations on meta instance
98              
99             sub get_all_slots {
100 11     11 1 1431 my $self = shift;
101 11         16 return @{$self->{'slots'}};
  11         66  
102             }
103              
104             sub get_all_attributes {
105 17     17 1 35 my $self = shift;
106 17         29 return @{$self->{attributes}};
  17         64  
107             }
108              
109             sub is_valid_slot {
110 0     0 1 0 my ($self, $slot_name) = @_;
111 0         0 exists $self->{'slot_hash'}->{$slot_name};
112             }
113              
114             # operations on created instances
115              
116             sub get_slot_value {
117 6652     6652 1 14590 my ($self, $instance, $slot_name) = @_;
118 6652         40597 $instance->{$slot_name};
119             }
120              
121             sub set_slot_value {
122 135086     135086 1 238620 my ($self, $instance, $slot_name, $value) = @_;
123 135086         674404 $instance->{$slot_name} = $value;
124             }
125              
126             sub initialize_slot {
127 1     1 1 4 my ($self, $instance, $slot_name) = @_;
128 1         3 return;
129             }
130              
131             sub deinitialize_slot {
132 19     19 1 56 my ( $self, $instance, $slot_name ) = @_;
133 19         51 delete $instance->{$slot_name};
134             }
135              
136             sub initialize_all_slots {
137 5     5 1 30 my ($self, $instance) = @_;
138 5         11 foreach my $slot_name ($self->get_all_slots) {
139 16         121 $self->initialize_slot($instance, $slot_name);
140             }
141             }
142              
143             sub deinitialize_all_slots {
144 0     0 1 0 my ($self, $instance) = @_;
145 0         0 foreach my $slot_name ($self->get_all_slots) {
146 0         0 $self->deinitialize_slot($instance, $slot_name);
147             }
148             }
149              
150             sub is_slot_initialized {
151 7371     7371 1 19720 my ($self, $instance, $slot_name, $value) = @_;
152 7371         31683 exists $instance->{$slot_name};
153             }
154              
155             sub weaken_slot_value {
156 54     54 1 202 my ($self, $instance, $slot_name) = @_;
157 54         338 weaken $instance->{$slot_name};
158             }
159              
160             sub slot_value_is_weak {
161 165     165 1 248 my ($self, $instance, $slot_name) = @_;
162 165         556 isweak $instance->{$slot_name};
163             }
164              
165             sub strengthen_slot_value {
166 1     1 1 5 my ($self, $instance, $slot_name) = @_;
167 1         4 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
168             }
169              
170             sub rebless_instance_structure {
171 126     126 1 417 my ($self, $instance, $metaclass) = @_;
172              
173             # we use $_[1] here because of t/cmop/rebless_overload.t regressions
174             # on 5.8.8
175 126         507 bless $_[1], $metaclass->name;
176             }
177              
178             sub is_dependent_on_superclasses {
179 21135     21135 0 54446 return; # for meta instances that require updates on inherited slot changes
180             }
181              
182             sub _get_mop_slot {
183 1     1   3 my ($self, $instance) = @_;
184 1         4 $self->get_slot_value($instance, $RESERVED_MOP_SLOT);
185             }
186              
187             sub _has_mop_slot {
188 17     17   41 my ($self, $instance) = @_;
189 17         50 $self->is_slot_initialized($instance, $RESERVED_MOP_SLOT);
190             }
191              
192             sub _set_mop_slot {
193 1688     1688   3372 my ($self, $instance, $value) = @_;
194 1688         2965 $self->set_slot_value($instance, $RESERVED_MOP_SLOT, $value);
195             }
196              
197             sub _clear_mop_slot {
198 1     1   3 my ($self, $instance) = @_;
199 1         4 $self->deinitialize_slot($instance, $RESERVED_MOP_SLOT);
200             }
201              
202             # inlinable operation snippets
203              
204 42022     42022 1 139671 sub is_inlinable { 1 }
205              
206             sub inline_create_instance {
207 12215     12215 1 26344 my ($self, $class_variable) = @_;
208 12215         49722 'bless {} => ' . $class_variable;
209             }
210              
211             sub inline_slot_access {
212 195355     195355 1 310520 my ($self, $instance, $slot_name) = @_;
213 195355         1199759 sprintf q[%s->{"%s"}], $instance, quotemeta($slot_name);
214             }
215              
216 331     331 1 1205 sub inline_get_is_lvalue { 1 }
217              
218             sub inline_get_slot_value {
219 32965     32965 1 66914 my ($self, $instance, $slot_name) = @_;
220 32965         70105 $self->inline_slot_access($instance, $slot_name);
221             }
222              
223             sub inline_set_slot_value {
224 154480     154480 1 286175 my ($self, $instance, $slot_name, $value) = @_;
225 154480         266396 $self->inline_slot_access($instance, $slot_name) . " = $value",
226             }
227              
228             sub inline_initialize_slot {
229 1     1 1 4 my ($self, $instance, $slot_name) = @_;
230 1         4 return '';
231             }
232              
233             sub inline_deinitialize_slot {
234 79     79 1 276 my ($self, $instance, $slot_name) = @_;
235 79         290 "delete " . $self->inline_slot_access($instance, $slot_name);
236             }
237             sub inline_is_slot_initialized {
238 7079     7079 1 16165 my ($self, $instance, $slot_name) = @_;
239 7079         17413 "exists " . $self->inline_slot_access($instance, $slot_name);
240             }
241              
242             sub inline_weaken_slot_value {
243 762     762 1 2614 my ($self, $instance, $slot_name) = @_;
244 762         2712 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
245             }
246              
247             sub inline_strengthen_slot_value {
248 1     1 1 4 my ($self, $instance, $slot_name) = @_;
249 1         4 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
250             }
251              
252             sub inline_rebless_instance_structure {
253 1     1 1 4 my ($self, $instance, $class_variable) = @_;
254 1         6 "bless $instance => $class_variable";
255             }
256              
257             sub _inline_get_mop_slot {
258 0     0   0 my ($self, $instance) = @_;
259 0         0 $self->inline_get_slot_value($instance, $RESERVED_MOP_SLOT);
260             }
261              
262             sub _inline_set_mop_slot {
263 21     21   56 my ($self, $instance, $value) = @_;
264 21         45 $self->inline_set_slot_value($instance, $RESERVED_MOP_SLOT, $value);
265             }
266              
267             sub _inline_clear_mop_slot {
268 0     0     my ($self, $instance) = @_;
269 0           $self->inline_deinitialize_slot($instance, $RESERVED_MOP_SLOT);
270             }
271              
272             1;
273              
274             # ABSTRACT: Instance Meta Object
275              
276             __END__
277              
278             =pod
279              
280             =encoding UTF-8
281              
282             =head1 NAME
283              
284             Class::MOP::Instance - Instance Meta Object
285              
286             =head1 VERSION
287              
288             version 2.2206
289              
290             =head1 DESCRIPTION
291              
292             The Instance Protocol controls the creation of object instances, and
293             the storage of attribute values in those instances.
294              
295             Using this API directly in your own code violates encapsulation, and
296             we recommend that you use the appropriate APIs in L<Class::MOP::Class>
297             and L<Class::MOP::Attribute> instead. Those APIs in turn call the
298             methods in this class as appropriate.
299              
300             This class also participates in generating inlined code by providing
301             snippets of code to access an object instance.
302              
303             =head1 METHODS
304              
305             =head2 Object construction
306              
307             =over 4
308              
309             =item B<< Class::MOP::Instance->new(%options) >>
310              
311             This method creates a new meta-instance object.
312              
313             It accepts the following keys in C<%options>:
314              
315             =over 8
316              
317             =item * associated_metaclass
318              
319             The L<Class::MOP::Class> object for which instances will be created.
320              
321             =item * attributes
322              
323             An array reference of L<Class::MOP::Attribute> objects. These are the
324             attributes which can be stored in each instance.
325              
326             =back
327              
328             =back
329              
330             =head2 Creating and altering instances
331              
332             =over 4
333              
334             =item B<< $metainstance->create_instance >>
335              
336             This method returns a reference blessed into the associated
337             metaclass's class.
338              
339             The default is to use a hash reference. Subclasses can override this.
340              
341             =item B<< $metainstance->clone_instance($instance) >>
342              
343             Given an instance, this method creates a new object by making
344             I<shallow> clone of the original.
345              
346             =back
347              
348             =head2 Introspection
349              
350             =over 4
351              
352             =item B<< $metainstance->associated_metaclass >>
353              
354             This returns the L<Class::MOP::Class> object associated with the
355             meta-instance object.
356              
357             =item B<< $metainstance->get_all_slots >>
358              
359             This returns a list of slot names stored in object instances. In
360             almost all cases, slot names correspond directly attribute names.
361              
362             =item B<< $metainstance->is_valid_slot($slot_name) >>
363              
364             This will return true if C<$slot_name> is a valid slot name.
365              
366             =item B<< $metainstance->get_all_attributes >>
367              
368             This returns a list of attributes corresponding to the attributes
369             passed to the constructor.
370              
371             =back
372              
373             =head2 Operations on Instance Structures
374              
375             It's important to understand that the meta-instance object is a
376             different entity from the actual instances it creates. For this
377             reason, any operations on the C<$instance_structure> always require
378             that the object instance be passed to the method.
379              
380             =over 4
381              
382             =item B<< $metainstance->get_slot_value($instance_structure, $slot_name) >>
383              
384             =item B<< $metainstance->set_slot_value($instance_structure, $slot_name, $value) >>
385              
386             =item B<< $metainstance->initialize_slot($instance_structure, $slot_name) >>
387              
388             =item B<< $metainstance->deinitialize_slot($instance_structure, $slot_name) >>
389              
390             =item B<< $metainstance->initialize_all_slots($instance_structure) >>
391              
392             =item B<< $metainstance->deinitialize_all_slots($instance_structure) >>
393              
394             =item B<< $metainstance->is_slot_initialized($instance_structure, $slot_name) >>
395              
396             =item B<< $metainstance->weaken_slot_value($instance_structure, $slot_name) >>
397              
398             =item B<< $metainstance->slot_value_is_weak($instance_structure, $slot_name) >>
399              
400             =item B<< $metainstance->strengthen_slot_value($instance_structure, $slot_name) >>
401              
402             =item B<< $metainstance->rebless_instance_structure($instance_structure, $new_metaclass) >>
403              
404             The exact details of what each method does should be fairly obvious
405             from the method name.
406              
407             =back
408              
409             =head2 Inlinable Instance Operations
410              
411             =over 4
412              
413             =item B<< $metainstance->is_inlinable >>
414              
415             This is a boolean that indicates whether or not slot access operations
416             can be inlined. By default it is true, but subclasses can override
417             this.
418              
419             =item B<< $metainstance->inline_create_instance($class_variable) >>
420              
421             This method expects a string that, I<when inlined>, will become a
422             class name. This would literally be something like C<'$class'>, not an
423             actual class name.
424              
425             It returns a snippet of code that creates a new object for the
426             class. This is something like C< bless {}, $class_name >.
427              
428             =item B<< $metainstance->inline_get_is_lvalue >>
429              
430             Returns whether or not C<inline_get_slot_value> is a valid lvalue. This can be
431             used to do extra optimizations when generating inlined methods.
432              
433             =item B<< $metainstance->inline_slot_access($instance_variable, $slot_name) >>
434              
435             =item B<< $metainstance->inline_get_slot_value($instance_variable, $slot_name) >>
436              
437             =item B<< $metainstance->inline_set_slot_value($instance_variable, $slot_name, $value) >>
438              
439             =item B<< $metainstance->inline_initialize_slot($instance_variable, $slot_name) >>
440              
441             =item B<< $metainstance->inline_deinitialize_slot($instance_variable, $slot_name) >>
442              
443             =item B<< $metainstance->inline_is_slot_initialized($instance_variable, $slot_name) >>
444              
445             =item B<< $metainstance->inline_weaken_slot_value($instance_variable, $slot_name) >>
446              
447             =item B<< $metainstance->inline_strengthen_slot_value($instance_variable, $slot_name) >>
448              
449             These methods all expect two arguments. The first is the name of a
450             variable, than when inlined, will represent the object
451             instance. Typically this will be a literal string like C<'$_[0]'>.
452              
453             The second argument is a slot name.
454              
455             The method returns a snippet of code that, when inlined, performs some
456             operation on the instance.
457              
458             =item B<< $metainstance->inline_rebless_instance_structure($instance_variable, $class_variable) >>
459              
460             This takes the name of a variable that will, when inlined, represent the object
461             instance, and the name of a variable that will represent the class to rebless
462             into, and returns code to rebless an instance into a class.
463              
464             =back
465              
466             =head2 Introspection
467              
468             =over 4
469              
470             =item B<< Class::MOP::Instance->meta >>
471              
472             This will return a L<Class::MOP::Class> instance for this class.
473              
474             It should also be noted that L<Class::MOP> will actually bootstrap
475             this module by installing a number of attribute meta-objects into its
476             metaclass.
477              
478             =back
479              
480             =head1 AUTHORS
481              
482             =over 4
483              
484             =item *
485              
486             Stevan Little <stevan@cpan.org>
487              
488             =item *
489              
490             Dave Rolsky <autarch@urth.org>
491              
492             =item *
493              
494             Jesse Luehrs <doy@cpan.org>
495              
496             =item *
497              
498             Shawn M Moore <sartak@cpan.org>
499              
500             =item *
501              
502             יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
503              
504             =item *
505              
506             Karen Etheridge <ether@cpan.org>
507              
508             =item *
509              
510             Florian Ragwitz <rafl@debian.org>
511              
512             =item *
513              
514             Hans Dieter Pearcey <hdp@cpan.org>
515              
516             =item *
517              
518             Chris Prather <chris@prather.org>
519              
520             =item *
521              
522             Matt S Trout <mstrout@cpan.org>
523              
524             =back
525              
526             =head1 COPYRIGHT AND LICENSE
527              
528             This software is copyright (c) 2006 by Infinity Interactive, Inc.
529              
530             This is free software; you can redistribute it and/or modify it under
531             the same terms as the Perl 5 programming language system itself.
532              
533             =cut