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.2205';
3              
4 451     451   135421 use strict;
  451         950  
  451         13148  
5 451     451   2420 use warnings;
  451         975  
  451         13173  
6              
7 451     451   2459 use Scalar::Util 'isweak', 'weaken', 'blessed';
  451         1124  
  451         25971  
8              
9 451     451   3829 use parent 'Class::MOP::Object';
  451         1831  
  451         3068  
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 57168 my ($class, @args) = @_;
16              
17 21139 50 33     143504 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         69529 my %options = @args;
26             # FIXME lazy_build
27 21139 50 50     72077 $options{slots} ||= [ map { $_->slots } @{ $options{attributes} || [] } ];
  172007         312259  
  21139         59670  
28 21139         41951 $options{slot_hash} = { map { $_ => undef } @{ $options{slots} } }; # FIXME lazy_build
  172008         331786  
  21139         44903  
29              
30 21139         69384 return \%options;
31             }
32              
33             sub new {
34 21139     21139 1 42349 my $class = shift;
35 21139         56330 my $options = $class->BUILDARGS(@_);
36              
37             # FIXME replace with a proper constructor
38 21139         168086 my $instance = $class->_new(%$options);
39              
40             # FIXME weak_ref => 1,
41 21139         91002 weaken($instance->{'associated_metaclass'});
42              
43 21139         65765 return $instance;
44             }
45              
46             sub _new {
47 18552     18552   32286 my $class = shift;
48 18552 100       44366 return Class::MOP::Class->initialize($class)->new_object(@_)
49             if $class ne __PACKAGE__;
50              
51 18541 50       64705 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         93933 } => $class;
68             }
69              
70 23595   66 23595   112399 sub _class_name { $_[0]->{_class_name} ||= $_[0]->associated_metaclass->name }
71              
72             sub create_instance {
73 23584     23584 1 38739 my $self = shift;
74 23584         58269 bless {}, $self->_class_name;
75             }
76              
77             sub clone_instance {
78 17     17 1 49 my ($self, $instance) = @_;
79              
80 17         53 my $clone = $self->create_instance;
81 17         66 for my $attr ($self->get_all_attributes) {
82 172 100       385 next unless $attr->has_value($instance);
83 162         359 for my $slot ($attr->slots) {
84 163         368 my $val = $self->get_slot_value($instance, $slot);
85 163         395 $self->set_slot_value($clone, $slot, $val);
86 163 100       308 $self->weaken_slot_value($clone, $slot)
87             if $self->slot_value_is_weak($instance, $slot);
88             }
89             }
90              
91 17 100       75 $self->_set_mop_slot($clone, $self->_get_mop_slot($instance))
92             if $self->_has_mop_slot($instance);
93              
94 17         58 return $clone;
95             }
96              
97             # operations on meta instance
98              
99             sub get_all_slots {
100 11     11 1 1324 my $self = shift;
101 11         17 return @{$self->{'slots'}};
  11         58  
102             }
103              
104             sub get_all_attributes {
105 17     17 1 72 my $self = shift;
106 17         29 return @{$self->{attributes}};
  17         102  
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 14790 my ($self, $instance, $slot_name) = @_;
118 6652         39572 $instance->{$slot_name};
119             }
120              
121             sub set_slot_value {
122 135043     135043 1 243851 my ($self, $instance, $slot_name, $value) = @_;
123 135043         679426 $instance->{$slot_name} = $value;
124             }
125              
126             sub initialize_slot {
127 1     1 1 4 my ($self, $instance, $slot_name) = @_;
128 1         2 return;
129             }
130              
131             sub deinitialize_slot {
132 19     19 1 55 my ( $self, $instance, $slot_name ) = @_;
133 19         55 delete $instance->{$slot_name};
134             }
135              
136             sub initialize_all_slots {
137 5     5 1 23 my ($self, $instance) = @_;
138 5         12 foreach my $slot_name ($self->get_all_slots) {
139 16         110 $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 19564 my ($self, $instance, $slot_name, $value) = @_;
152 7371         31172 exists $instance->{$slot_name};
153             }
154              
155             sub weaken_slot_value {
156 54     54 1 211 my ($self, $instance, $slot_name) = @_;
157 54         359 weaken $instance->{$slot_name};
158             }
159              
160             sub slot_value_is_weak {
161 165     165 1 250 my ($self, $instance, $slot_name) = @_;
162 165         583 isweak $instance->{$slot_name};
163             }
164              
165             sub strengthen_slot_value {
166 1     1 1 4 my ($self, $instance, $slot_name) = @_;
167 1         3 $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 353 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         502 bless $_[1], $metaclass->name;
176             }
177              
178             sub is_dependent_on_superclasses {
179 21135     21135 0 55068 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         3 $self->get_slot_value($instance, $RESERVED_MOP_SLOT);
185             }
186              
187             sub _has_mop_slot {
188 17     17   48 my ($self, $instance) = @_;
189 17         44 $self->is_slot_initialized($instance, $RESERVED_MOP_SLOT);
190             }
191              
192             sub _set_mop_slot {
193 1688     1688   3828 my ($self, $instance, $value) = @_;
194 1688         3346 $self->set_slot_value($instance, $RESERVED_MOP_SLOT, $value);
195             }
196              
197             sub _clear_mop_slot {
198 1     1   2 my ($self, $instance) = @_;
199 1         4 $self->deinitialize_slot($instance, $RESERVED_MOP_SLOT);
200             }
201              
202             # inlinable operation snippets
203              
204 42022     42022 1 139938 sub is_inlinable { 1 }
205              
206             sub inline_create_instance {
207 12215     12215 1 26794 my ($self, $class_variable) = @_;
208 12215         49910 'bless {} => ' . $class_variable;
209             }
210              
211             sub inline_slot_access {
212 195355     195355 1 311484 my ($self, $instance, $slot_name) = @_;
213 195355         1204322 sprintf q[%s->{"%s"}], $instance, quotemeta($slot_name);
214             }
215              
216 331     331 1 1201 sub inline_get_is_lvalue { 1 }
217              
218             sub inline_get_slot_value {
219 32965     32965 1 67234 my ($self, $instance, $slot_name) = @_;
220 32965         70208 $self->inline_slot_access($instance, $slot_name);
221             }
222              
223             sub inline_set_slot_value {
224 154480     154480 1 290343 my ($self, $instance, $slot_name, $value) = @_;
225 154480         267345 $self->inline_slot_access($instance, $slot_name) . " = $value",
226             }
227              
228             sub inline_initialize_slot {
229 1     1 1 3 my ($self, $instance, $slot_name) = @_;
230 1         5 return '';
231             }
232              
233             sub inline_deinitialize_slot {
234 79     79 1 311 my ($self, $instance, $slot_name) = @_;
235 79         296 "delete " . $self->inline_slot_access($instance, $slot_name);
236             }
237             sub inline_is_slot_initialized {
238 7079     7079 1 16221 my ($self, $instance, $slot_name) = @_;
239 7079         17449 "exists " . $self->inline_slot_access($instance, $slot_name);
240             }
241              
242             sub inline_weaken_slot_value {
243 762     762 1 2547 my ($self, $instance, $slot_name) = @_;
244 762         2816 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   49 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.2205
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