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.2203';
3              
4 463     463   168387 use strict;
  463         854  
  463         12390  
5 463     463   2072 use warnings;
  463         791  
  463         11628  
6              
7 463     463   2187 use Scalar::Util 'isweak', 'weaken', 'blessed';
  463         908  
  463         21920  
8              
9 463     463   3352 use parent 'Class::MOP::Object';
  463         1377  
  463         2431  
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 21726     21726 0 50573 my ($class, @args) = @_;
16              
17 21726 50 33     127499 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 21726         61752 my %options = @args;
26             # FIXME lazy_build
27 21726 50 50     64317 $options{slots} ||= [ map { $_->slots } @{ $options{attributes} || [] } ];
  176814         279964  
  21726         53238  
28 21726         36915 $options{slot_hash} = { map { $_ => undef } @{ $options{slots} } }; # FIXME lazy_build
  176815         292733  
  21726         39358  
29              
30 21726         61009 return \%options;
31             }
32              
33             sub new {
34 21726     21726 1 37219 my $class = shift;
35 21726         49647 my $options = $class->BUILDARGS(@_);
36              
37             # FIXME replace with a proper constructor
38 21726         148339 my $instance = $class->_new(%$options);
39              
40             # FIXME weak_ref => 1,
41 21726         82789 weaken($instance->{'associated_metaclass'});
42              
43 21726         58624 return $instance;
44             }
45              
46             sub _new {
47 19096     19096   28183 my $class = shift;
48 19096 100       39004 return Class::MOP::Class->initialize($class)->new_object(@_)
49             if $class ne __PACKAGE__;
50              
51 19085 50       59600 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 19085         85637 } => $class;
68             }
69              
70 24059   66 24059   96124 sub _class_name { $_[0]->{_class_name} ||= $_[0]->associated_metaclass->name }
71              
72             sub create_instance {
73 24048     24048 1 35435 my $self = shift;
74 24048         52239 bless {}, $self->_class_name;
75             }
76              
77             sub clone_instance {
78 17     17 1 37 my ($self, $instance) = @_;
79              
80 17         42 my $clone = $self->create_instance;
81 17         55 for my $attr ($self->get_all_attributes) {
82 172 100       322 next unless $attr->has_value($instance);
83 162         286 for my $slot ($attr->slots) {
84 163         313 my $val = $self->get_slot_value($instance, $slot);
85 163         307 $self->set_slot_value($clone, $slot, $val);
86 163 100       244 $self->weaken_slot_value($clone, $slot)
87             if $self->slot_value_is_weak($instance, $slot);
88             }
89             }
90              
91 17 100       58 $self->_set_mop_slot($clone, $self->_get_mop_slot($instance))
92             if $self->_has_mop_slot($instance);
93              
94 17         39 return $clone;
95             }
96              
97             # operations on meta instance
98              
99             sub get_all_slots {
100 11     11 1 1515 my $self = shift;
101 11         12 return @{$self->{'slots'}};
  11         49  
102             }
103              
104             sub get_all_attributes {
105 17     17 1 28 my $self = shift;
106 17         26 return @{$self->{attributes}};
  17         50  
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 6782     6782 1 12617 my ($self, $instance, $slot_name) = @_;
118 6782         33030 $instance->{$slot_name};
119             }
120              
121             sub set_slot_value {
122 137883     137883 1 212046 my ($self, $instance, $slot_name, $value) = @_;
123 137883         591505 $instance->{$slot_name} = $value;
124             }
125              
126             sub initialize_slot {
127 1     1 1 3 my ($self, $instance, $slot_name) = @_;
128 1         2 return;
129             }
130              
131             sub deinitialize_slot {
132 19     19 1 39 my ( $self, $instance, $slot_name ) = @_;
133 19         45 delete $instance->{$slot_name};
134             }
135              
136             sub initialize_all_slots {
137 5     5 1 21 my ($self, $instance) = @_;
138 5         9 foreach my $slot_name ($self->get_all_slots) {
139 16         88 $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 7503     7503 1 18133 my ($self, $instance, $slot_name, $value) = @_;
152 7503         26582 exists $instance->{$slot_name};
153             }
154              
155             sub weaken_slot_value {
156 54     54 1 167 my ($self, $instance, $slot_name) = @_;
157 54         294 weaken $instance->{$slot_name};
158             }
159              
160             sub slot_value_is_weak {
161 165     165 1 214 my ($self, $instance, $slot_name) = @_;
162 165         492 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 286 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         422 bless $_[1], $metaclass->name;
176             }
177              
178             sub is_dependent_on_superclasses {
179 21722     21722 0 48670 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   35 my ($self, $instance) = @_;
189 17         34 $self->is_slot_initialized($instance, $RESERVED_MOP_SLOT);
190             }
191              
192             sub _set_mop_slot {
193 1688     1688   2745 my ($self, $instance, $value) = @_;
194 1688         2692 $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         5 $self->deinitialize_slot($instance, $RESERVED_MOP_SLOT);
200             }
201              
202             # inlinable operation snippets
203              
204 43114     43114 1 124241 sub is_inlinable { 1 }
205              
206             sub inline_create_instance {
207 12573     12573 1 23069 my ($self, $class_variable) = @_;
208 12573         44345 'bless {} => ' . $class_variable;
209             }
210              
211             sub inline_slot_access {
212 200803     200803 1 279294 my ($self, $instance, $slot_name) = @_;
213 200803         1077487 sprintf q[%s->{"%s"}], $instance, quotemeta($slot_name);
214             }
215              
216 331     331 1 1068 sub inline_get_is_lvalue { 1 }
217              
218             sub inline_get_slot_value {
219 33842     33842 1 60104 my ($self, $instance, $slot_name) = @_;
220 33842         62928 $self->inline_slot_access($instance, $slot_name);
221             }
222              
223             sub inline_set_slot_value {
224 158848     158848 1 256279 my ($self, $instance, $slot_name, $value) = @_;
225 158848         238850 $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         3 return '';
231             }
232              
233             sub inline_deinitialize_slot {
234 80     80 1 260 my ($self, $instance, $slot_name) = @_;
235 80         256 "delete " . $self->inline_slot_access($instance, $slot_name);
236             }
237             sub inline_is_slot_initialized {
238 7259     7259 1 14276 my ($self, $instance, $slot_name) = @_;
239 7259         15610 "exists " . $self->inline_slot_access($instance, $slot_name);
240             }
241              
242             sub inline_weaken_slot_value {
243 784     784 1 2250 my ($self, $instance, $slot_name) = @_;
244 784         2342 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         3 $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         4 "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   37 my ($self, $instance, $value) = @_;
264 21         43 $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.2203
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