Fix too much quotemeta in Instance metaclass
[gitmo/Class-MOP.git] / lib / Class / MOP / Instance.pm
CommitLineData
24869f62 1
2package Class::MOP::Instance;
3
4use strict;
5use warnings;
6
fa16e528 7use Scalar::Util 'weaken', 'blessed';
24869f62 8
4b18c1b3 9our $VERSION = '0.91';
d519662a 10$VERSION = eval $VERSION;
f0480c45 11our $AUTHORITY = 'cpan:STEVAN';
24869f62 12
d7b2249e 13use base 'Class::MOP::Object';
24869f62 14
63d08a9e 15sub BUILDARGS {
d43737b3 16 my ($class, @args) = @_;
17
18 if ( @args == 1 ) {
63d08a9e 19 unshift @args, "associated_metaclass";
d43737b3 20 } elsif ( @args >= 2 && blessed($args[0]) && $args[0]->isa("Class::MOP::Class") ) {
21 # compat mode
22 my ( $meta, @attrs ) = @args;
63d08a9e 23 @args = ( associated_metaclass => $meta, attributes => \@attrs );
d43737b3 24 }
25
26 my %options = @args;
7c7fd869 27 # FIXME lazy_build
d43737b3 28 $options{slots} ||= [ map { $_->slots } @{ $options{attributes} || [] } ];
63d08a9e 29 $options{slot_hash} = { map { $_ => undef } @{ $options{slots} } }; # FIXME lazy_build
30
31 return \%options;
32}
33
34sub new {
35 my $class = shift;
36 my $options = $class->BUILDARGS(@_);
d43737b3 37
38 # FIXME replace with a proper constructor
b4b5d65a 39 my $instance = $class->_new(%$options);
40
41 # FIXME weak_ref => 1,
42 weaken($instance->{'associated_metaclass'});
43
44 return $instance;
45}
46
47sub _new {
ec9e38e5 48 my $class = shift;
49 return Class::MOP::Class->initialize($class)->new_object(@_)
50 if $class ne __PACKAGE__;
51
52 my $params = @_ == 1 ? $_[0] : {@_};
53 return bless {
fc3ddd1d 54 # NOTE:
55 # I am not sure that it makes
56 # sense to pass in the meta
8d2d4c67 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(),
fc3ddd1d 61 # which is *probably* a safe
8d2d4c67 62 # assumption,.. but you can
fc3ddd1d 63 # never tell <:)
ec9e38e5 64 'associated_metaclass' => $params->{associated_metaclass},
65 'attributes' => $params->{attributes},
66 'slots' => $params->{slots},
67 'slot_hash' => $params->{slot_hash},
8d2d4c67 68 } => $class;
24869f62 69}
70
74890687 71sub _class_name { $_[0]->{_class_name} ||= $_[0]->associated_metaclass->name }
72
73sub associated_metaclass { $_[0]{'associated_metaclass'} }
c23184fc 74
49c93440 75sub create_instance {
76 my $self = shift;
becd03c6 77 bless {}, $self->_class_name;
2d711cc8 78}
79
becd03c6 80# for compatibility
49c93440 81sub bless_instance_structure {
c7e28c19 82 Carp::cluck('The bless_instance_structure method is deprecated.'
83 . " It will be removed in a future release.\n");
cf11901e 84
49c93440 85 my ($self, $instance_structure) = @_;
74890687 86 bless $instance_structure, $self->_class_name;
2d711cc8 87}
88
f7259199 89sub clone_instance {
90 my ($self, $instance) = @_;
becd03c6 91 bless { %$instance }, $self->_class_name;
f7259199 92}
93
2d711cc8 94# operations on meta instance
95
eb49acde 96sub get_all_slots {
97 my $self = shift;
7c7fd869 98 return @{$self->{'slots'}};
f7259199 99}
100
0b5d46da 101sub get_all_attributes {
102 my $self = shift;
103 return @{$self->{attributes}};
104}
105
f7259199 106sub is_valid_slot {
107 my ($self, $slot_name) = @_;
7c7fd869 108 exists $self->{'slot_hash'}->{$slot_name};
839ea973 109}
110
2d711cc8 111# operations on created instances
112
839ea973 113sub get_slot_value {
2bab2be6 114 my ($self, $instance, $slot_name) = @_;
230472a7 115 $instance->{$slot_name};
839ea973 116}
117
2bab2be6 118sub set_slot_value {
119 my ($self, $instance, $slot_name, $value) = @_;
120 $instance->{$slot_name} = $value;
121}
122
2d711cc8 123sub initialize_slot {
49c93440 124 my ($self, $instance, $slot_name) = @_;
a007159d 125 return;
2d711cc8 126}
127
7d28758b 128sub deinitialize_slot {
129 my ( $self, $instance, $slot_name ) = @_;
130 delete $instance->{$slot_name};
131}
132
c174112e 133sub initialize_all_slots {
134 my ($self, $instance) = @_;
135 foreach my $slot_name ($self->get_all_slots) {
136 $self->initialize_slot($instance, $slot_name);
137 }
138}
139
7d28758b 140sub deinitialize_all_slots {
141 my ($self, $instance) = @_;
142 foreach my $slot_name ($self->get_all_slots) {
143 $self->deinitialize_slot($instance, $slot_name);
144 }
145}
146
49c93440 147sub is_slot_initialized {
148 my ($self, $instance, $slot_name, $value) = @_;
230472a7 149 exists $instance->{$slot_name};
2bab2be6 150}
839ea973 151
5582521c 152sub weaken_slot_value {
69e3ab0a 153 my ($self, $instance, $slot_name) = @_;
154 weaken $instance->{$slot_name};
5582521c 155}
156
157sub strengthen_slot_value {
69e3ab0a 158 my ($self, $instance, $slot_name) = @_;
159 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
5582521c 160}
161
3d9e4646 162sub rebless_instance_structure {
163 my ($self, $instance, $metaclass) = @_;
feb93c85 164
165 # we use $_[1] here because of t/306_rebless_overload.t regressions on 5.8.8
166 bless $_[1], $metaclass->name;
3d9e4646 167}
168
da5680be 169sub is_dependent_on_superclasses {
170 return; # for meta instances that require updates on inherited slot changes
171}
172
ee7c0467 173# inlinable operation snippets
174
c0cbf4d9 175sub is_inlinable { 1 }
176
177sub inline_create_instance {
178 my ($self, $class_variable) = @_;
179 'bless {} => ' . $class_variable;
180}
181
ee7c0467 182sub inline_slot_access {
183 my ($self, $instance, $slot_name) = @_;
80d7d635 184 $slot_name =~ s/(['\\])/\\$1/g; # In '', only "'" and "\\" are meta characters.
185 sprintf q[%s->{'%s'}], $instance, $slot_name;
ee7c0467 186}
187
188sub inline_get_slot_value {
189 my ($self, $instance, $slot_name) = @_;
230472a7 190 $self->inline_slot_access($instance, $slot_name);
ee7c0467 191}
192
193sub inline_set_slot_value {
194 my ($self, $instance, $slot_name, $value) = @_;
8d2d4c67 195 $self->inline_slot_access($instance, $slot_name) . " = $value",
ee7c0467 196}
197
198sub inline_initialize_slot {
199 my ($self, $instance, $slot_name) = @_;
a007159d 200 return '';
ee7c0467 201}
202
7d28758b 203sub inline_deinitialize_slot {
204 my ($self, $instance, $slot_name) = @_;
205 "delete " . $self->inline_slot_access($instance, $slot_name);
206}
ee7c0467 207sub inline_is_slot_initialized {
208 my ($self, $instance, $slot_name) = @_;
230472a7 209 "exists " . $self->inline_slot_access($instance, $slot_name);
ee7c0467 210}
211
212sub inline_weaken_slot_value {
213 my ($self, $instance, $slot_name) = @_;
214 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
215}
216
217sub 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));
220}
221
bc3c58a0 222sub inline_rebless_instance_structure {
223 my ($self, $instance, $class_variable) = @_;
224 "bless $instance => $class_variable";
225}
226
24869f62 2271;
228
229__END__
230
231=pod
232
8d2d4c67 233=head1 NAME
24869f62 234
235Class::MOP::Instance - Instance Meta Object
236
24869f62 237=head1 DESCRIPTION
238
1cbf42df 239The Instance Protocol controls the creation of object instances, and
88bb3cf1 240the storage of attribute values in those instances.
241
242Using this API directly in your own code violates encapsulation, and
243we recommend that you use the appropriate APIs in L<Class::MOP::Class>
244and L<Class::MOP::Attribute> instead. Those APIs in turn call the
245methods in this class as appropriate.
246
247This class also participates in generating inlined code by providing
248snippets of code to access an object instance.
9fa4d0b4 249
24869f62 250=head1 METHODS
251
88bb3cf1 252=head2 Object construction
253
24869f62 254=over 4
255
88bb3cf1 256=item B<< Class::MOP::Instance->new(%options) >>
9fa4d0b4 257
88bb3cf1 258This method creates a new meta-instance object.
9fa4d0b4 259
88bb3cf1 260It accepts the following keys in C<%options>:
63d08a9e 261
88bb3cf1 262=over 8
63d08a9e 263
88bb3cf1 264=item * associated_metaclass
9fa4d0b4 265
88bb3cf1 266The L<Class::MOP::Class> object for which instances will be created.
9fa4d0b4 267
88bb3cf1 268=item * attributes
9fa4d0b4 269
88bb3cf1 270An array reference of L<Class::MOP::Attribute> objects. These are the
271attributes which can be stored in each instance.
9fa4d0b4 272
88bb3cf1 273=back
24869f62 274
88bb3cf1 275=back
58287a97 276
88bb3cf1 277=head2 Creating and altering instances
0e76a376 278
88bb3cf1 279=over 4
839ea973 280
88bb3cf1 281=item B<< $metainstance->create_instance >>
0e76a376 282
88bb3cf1 283This method returns a reference blessed into the associated
284metaclass's class.
becd03c6 285
88bb3cf1 286The default is to use a hash reference. Subclasses can override this.
f7259199 287
88bb3cf1 288=item B<< $metainstance->clone_instance($instance) >>
289
290Given an instance, this method creates a new object by making
291I<shallow> clone of the original.
127d39a7 292
9fa4d0b4 293=back
839ea973 294
98bf345b 295=head2 Introspection
58287a97 296
9fa4d0b4 297=over 4
298
88bb3cf1 299=item B<< $metainstance->associated_metaclass >>
c23184fc 300
88bb3cf1 301This returns the L<Class::MOP::Class> object associated with the
302meta-instance object.
127d39a7 303
88bb3cf1 304=item B<< $metainstance->get_all_slots >>
9fa4d0b4 305
88bb3cf1 306This returns a list of slot names stored in object instances. In
307almost all cases, slot names correspond directly attribute names.
58287a97 308
88bb3cf1 309=item B<< $metainstance->is_valid_slot($slot_name) >>
f7259199 310
127d39a7 311This will return true if C<$slot_name> is a valid slot name.
312
88bb3cf1 313=item B<< $metainstance->get_all_attributes >>
da5680be 314
88bb3cf1 315This returns a list of attributes corresponding to the attributes
316passed to the constructor.
0202ee96 317
24869f62 318=back
319
9fa4d0b4 320=head2 Operations on Instance Structures
321
88bb3cf1 322It's important to understand that the meta-instance object is a
323different entity from the actual instances it creates. For this
324reason, any operations on the C<$instance_structure> always require
325that the object instance be passed to the method.
127d39a7 326
24869f62 327=over 4
328
88bb3cf1 329=item B<< $metainstance->get_slot_value($instance_structure, $slot_name) >>
330
331=item B<< $metainstance->set_slot_value($instance_structure, $slot_name, $value) >>
24869f62 332
88bb3cf1 333=item B<< $metainstance->initialize_slot($instance_structure, $slot_name) >>
9fa4d0b4 334
88bb3cf1 335=item B<< $metainstance->deinitialize_slot($instance_structure, $slot_name) >>
9fa4d0b4 336
88bb3cf1 337=item B<< $metainstance->initialize_all_slots($instance_structure) >>
7d28758b 338
88bb3cf1 339=item B<< $metainstance->deinitialize_all_slots($instance_structure) >>
9fa4d0b4 340
88bb3cf1 341=item B<< $metainstance->is_slot_initialized($instance_structure, $slot_name) >>
7d28758b 342
88bb3cf1 343=item B<< $metainstance->weaken_slot_value($instance_structure, $slot_name) >>
24869f62 344
88bb3cf1 345=item B<< $metainstance->strengthen_slot_value($instance_structure, $slot_name) >>
ee7c0467 346
88bb3cf1 347=item B<< $metainstance->rebless_instance_structure($instance_structure, $new_metaclass) >>
ee7c0467 348
88bb3cf1 349The exact details of what each method does should be fairly obvious
350from the method name.
5fdf066d 351
ee7c0467 352=back
353
88bb3cf1 354=head2 Inlinable Instance Operations
ee7c0467 355
356=over 4
357
88bb3cf1 358=item B<< $metainstance->is_inlinable >>
c0cbf4d9 359
88bb3cf1 360This is a boolean that indicates whether or not slot access operations
361can be inlined. By default it is true, but subclasses can override
362this.
c0cbf4d9 363
88bb3cf1 364=item B<< $metainstance->inline_create_instance($class_variable) >>
495af518 365
88bb3cf1 366This method expects a string that, I<when inlined>, will become a
367class name. This would literally be something like C<'$class'>, not an
368actual class name.
ee7c0467 369
88bb3cf1 370It returns a snippet of code that creates a new object for the
371class. This is something like C< bless {}, $class_name >.
ee7c0467 372
88bb3cf1 373=item B<< $metainstance->inline_slot_access($instance_variable, $slot_name) >>
ee7c0467 374
88bb3cf1 375=item B<< $metainstance->inline_get_slot_value($instance_variable, $slot_name) >>
ee7c0467 376
88bb3cf1 377=item B<< $metainstance->inline_set_slot_value($instance_variable, $slot_name, $value) >>
378
379=item B<< $metainstance->inline_initialize_slot($instance_variable, $slot_name) >>
380
381=item B<< $metainstance->inline_deinitialize_slot($instance_variable, $slot_name) >>
382
383=item B<< $metainstance->inline_is_slot_initialized($instance_variable, $slot_name) >>
384
385=item B<< $metainstance->inline_weaken_slot_value($instance_variable, $slot_name) >>
386
387=item B<< $metainstance->inline_strengthen_slot_value($instance_variable, $slot_name) >>
388
389These methods all expect two arguments. The first is the name of a
390variable, than when inlined, will represent the object
391instance. Typically this will be a literal string like C<'$_[0]'>.
392
393The second argument is a slot name.
394
395The method returns a snippet of code that, when inlined, performs some
396operation on the instance.
397
0fab42eb 398=item B<< $metainstance->inline_rebless_instance_structure($instance_variable, $class_variable) >>
399
400This takes the name of a variable that will, when inlined, represent the object
401instance, and the name of a variable that will represent the class to rebless
402into, and returns code to rebless an instance into a class.
403
88bb3cf1 404=back
405
406=head2 Introspection
407
408=over 4
7d28758b 409
88bb3cf1 410=item B<< Class::MOP::Instance->meta >>
5582521c 411
88bb3cf1 412This will return a L<Class::MOP::Class> instance for this class.
5582521c 413
88bb3cf1 414It should also be noted that L<Class::MOP> will actually bootstrap
415this module by installing a number of attribute meta-objects into its
416metaclass.
5582521c 417
24869f62 418=back
419
1a09d9cc 420=head1 AUTHORS
24869f62 421
9fa4d0b4 422Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
423
24869f62 424Stevan Little E<lt>stevan@iinteractive.comE<gt>
425
426=head1 COPYRIGHT AND LICENSE
427
070bb6c9 428Copyright 2006-2009 by Infinity Interactive, Inc.
24869f62 429
430L<http://www.iinteractive.com>
431
432This library is free software; you can redistribute it and/or modify
8d2d4c67 433it under the same terms as Perl itself.
24869f62 434
84ef30d1 435=cut
5582521c 436