_enw for Method::Constructor
[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
2e5c1a3f 9our $VERSION = '0.65';
f0480c45 10our $AUTHORITY = 'cpan:STEVAN';
24869f62 11
d7b2249e 12use base 'Class::MOP::Object';
24869f62 13
63d08a9e 14sub BUILDARGS {
d43737b3 15 my ($class, @args) = @_;
16
17 if ( @args == 1 ) {
63d08a9e 18 unshift @args, "associated_metaclass";
d43737b3 19 } elsif ( @args >= 2 && blessed($args[0]) && $args[0]->isa("Class::MOP::Class") ) {
20 # compat mode
21 my ( $meta, @attrs ) = @args;
63d08a9e 22 @args = ( associated_metaclass => $meta, attributes => \@attrs );
d43737b3 23 }
24
25 my %options = @args;
7c7fd869 26 # FIXME lazy_build
d43737b3 27 $options{slots} ||= [ map { $_->slots } @{ $options{attributes} || [] } ];
63d08a9e 28 $options{slot_hash} = { map { $_ => undef } @{ $options{slots} } }; # FIXME lazy_build
29
30 return \%options;
31}
32
33sub new {
34 my $class = shift;
35 my $options = $class->BUILDARGS(@_);
d43737b3 36
37 # FIXME replace with a proper constructor
c23184fc 38 my $instance = bless {
fc3ddd1d 39 # NOTE:
40 # I am not sure that it makes
41 # sense to pass in the meta
8d2d4c67 42 # The ideal would be to just
43 # pass in the class name, but
44 # that is placing too much of
45 # an assumption on bless(),
fc3ddd1d 46 # which is *probably* a safe
8d2d4c67 47 # assumption,.. but you can
fc3ddd1d 48 # never tell <:)
63d08a9e 49 'associated_metaclass' => $options->{associated_metaclass},
74890687 50 'attributes' => $options->{attributes},
51 'slots' => $options->{slots},
52 'slot_hash' => $options->{slot_hash},
8d2d4c67 53 } => $class;
54
d43737b3 55 # FIXME weak_ref => 1,
63d08a9e 56 weaken($instance->{'associated_metaclass'});
8d2d4c67 57
c23184fc 58 return $instance;
24869f62 59}
60
74890687 61sub _class_name { $_[0]->{_class_name} ||= $_[0]->associated_metaclass->name }
62
63sub associated_metaclass { $_[0]{'associated_metaclass'} }
c23184fc 64
49c93440 65sub create_instance {
66 my $self = shift;
becd03c6 67 bless {}, $self->_class_name;
2d711cc8 68}
69
becd03c6 70# for compatibility
49c93440 71sub bless_instance_structure {
72 my ($self, $instance_structure) = @_;
74890687 73 bless $instance_structure, $self->_class_name;
2d711cc8 74}
75
f7259199 76sub clone_instance {
77 my ($self, $instance) = @_;
becd03c6 78 bless { %$instance }, $self->_class_name;
f7259199 79}
80
2d711cc8 81# operations on meta instance
82
eb49acde 83sub get_all_slots {
84 my $self = shift;
7c7fd869 85 return @{$self->{'slots'}};
f7259199 86}
87
88sub is_valid_slot {
89 my ($self, $slot_name) = @_;
7c7fd869 90 exists $self->{'slot_hash'}->{$slot_name};
839ea973 91}
92
2d711cc8 93# operations on created instances
94
839ea973 95sub get_slot_value {
2bab2be6 96 my ($self, $instance, $slot_name) = @_;
230472a7 97 $instance->{$slot_name};
839ea973 98}
99
2bab2be6 100sub set_slot_value {
101 my ($self, $instance, $slot_name, $value) = @_;
102 $instance->{$slot_name} = $value;
103}
104
2d711cc8 105sub initialize_slot {
49c93440 106 my ($self, $instance, $slot_name) = @_;
a007159d 107 return;
2d711cc8 108}
109
7d28758b 110sub deinitialize_slot {
111 my ( $self, $instance, $slot_name ) = @_;
112 delete $instance->{$slot_name};
113}
114
c174112e 115sub initialize_all_slots {
116 my ($self, $instance) = @_;
117 foreach my $slot_name ($self->get_all_slots) {
118 $self->initialize_slot($instance, $slot_name);
119 }
120}
121
7d28758b 122sub deinitialize_all_slots {
123 my ($self, $instance) = @_;
124 foreach my $slot_name ($self->get_all_slots) {
125 $self->deinitialize_slot($instance, $slot_name);
126 }
127}
128
49c93440 129sub is_slot_initialized {
130 my ($self, $instance, $slot_name, $value) = @_;
230472a7 131 exists $instance->{$slot_name};
2bab2be6 132}
839ea973 133
5582521c 134sub weaken_slot_value {
69e3ab0a 135 my ($self, $instance, $slot_name) = @_;
136 weaken $instance->{$slot_name};
5582521c 137}
138
139sub strengthen_slot_value {
69e3ab0a 140 my ($self, $instance, $slot_name) = @_;
141 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
5582521c 142}
143
3d9e4646 144sub rebless_instance_structure {
145 my ($self, $instance, $metaclass) = @_;
146 bless $instance, $metaclass->name;
147}
148
da5680be 149sub is_dependent_on_superclasses {
150 return; # for meta instances that require updates on inherited slot changes
151}
152
ee7c0467 153# inlinable operation snippets
154
c0cbf4d9 155sub is_inlinable { 1 }
156
157sub inline_create_instance {
158 my ($self, $class_variable) = @_;
159 'bless {} => ' . $class_variable;
160}
161
ee7c0467 162sub inline_slot_access {
163 my ($self, $instance, $slot_name) = @_;
164 sprintf "%s->{%s}", $instance, $slot_name;
165}
166
167sub inline_get_slot_value {
168 my ($self, $instance, $slot_name) = @_;
230472a7 169 $self->inline_slot_access($instance, $slot_name);
ee7c0467 170}
171
172sub inline_set_slot_value {
173 my ($self, $instance, $slot_name, $value) = @_;
8d2d4c67 174 $self->inline_slot_access($instance, $slot_name) . " = $value",
ee7c0467 175}
176
177sub inline_initialize_slot {
178 my ($self, $instance, $slot_name) = @_;
a007159d 179 return '';
ee7c0467 180}
181
7d28758b 182sub inline_deinitialize_slot {
183 my ($self, $instance, $slot_name) = @_;
184 "delete " . $self->inline_slot_access($instance, $slot_name);
185}
ee7c0467 186sub inline_is_slot_initialized {
187 my ($self, $instance, $slot_name) = @_;
230472a7 188 "exists " . $self->inline_slot_access($instance, $slot_name);
ee7c0467 189}
190
191sub inline_weaken_slot_value {
192 my ($self, $instance, $slot_name) = @_;
193 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
194}
195
196sub inline_strengthen_slot_value {
197 my ($self, $instance, $slot_name) = @_;
198 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
199}
200
24869f62 2011;
202
203__END__
204
205=pod
206
8d2d4c67 207=head1 NAME
24869f62 208
209Class::MOP::Instance - Instance Meta Object
210
24869f62 211=head1 DESCRIPTION
212
bc9e7815 213The meta instance is used by attributes for low level storage.
214
215Using this API generally violates attribute encapsulation and is not
98bf345b 216recommended, instead look at L<Class::MOP::Attribute/get_value>,
217L<Class::MOP::Attribute/set_value> for the recommended way to fiddle with
218attribute values in a generic way, independent of how/whether accessors have
bc9e7815 219been defined. Accessors can be found using L<Class::MOP::Class/get_attribute>.
9fa4d0b4 220
8d2d4c67 221This may seem like over-abstraction, but by abstracting
222this process into a sub-protocol we make it possible to
223easily switch the details of how an object's instance is
224stored with minimal impact. In most cases just subclassing
225this class will be all you need to do (see the examples;
226F<examples/ArrayBasedStorage.pod> and
1becdfcc 227F<examples/InsideOutClass.pod> for details).
9fa4d0b4 228
24869f62 229=head1 METHODS
230
231=over 4
232
63d08a9e 233=item B<new %args>
9fa4d0b4 234
8d2d4c67 235Creates a new instance meta-object and gathers all the slots from
9fa4d0b4 236the list of C<@attrs> given.
237
63d08a9e 238=item B<BUILDARGS>
239
240Processes arguments for compatibility.
241
9fa4d0b4 242=item B<meta>
243
63d08a9e 244Returns the metaclass of L<Class::MOP::Instance>.
9fa4d0b4 245
246=back
247
248=head2 Creation of Instances
249
250=over 4
24869f62 251
58287a97 252=item B<create_instance>
253
becd03c6 254This creates the appropriate structure needed for the instance and blesses it.
0e76a376 255
9fa4d0b4 256=item B<bless_instance_structure ($instance_structure)>
839ea973 257
9fa4d0b4 258This does just exactly what it says it does.
0e76a376 259
becd03c6 260This method has been deprecated but remains for compatibility reasons. None of
261the subclasses of L<Class::MOP::Instance> ever bothered to actually make use of
262it, so it was deemed unnecessary fluff.
263
f7259199 264=item B<clone_instance ($instance_structure)>
265
becd03c6 266Creates a shallow clone of $instance_structure.
127d39a7 267
9fa4d0b4 268=back
839ea973 269
98bf345b 270=head2 Introspection
58287a97 271
8d2d4c67 272NOTE: There might be more methods added to this part of the API,
9fa4d0b4 273we will add then when we need them basically.
58287a97 274
9fa4d0b4 275=over 4
276
c23184fc 277=item B<associated_metaclass>
278
127d39a7 279This returns the metaclass associated with this instance.
280
9fa4d0b4 281=item B<get_all_slots>
282
8d2d4c67 283This will return the current list of slots based on what was
9fa4d0b4 284given to this object in C<new>.
58287a97 285
f7259199 286=item B<is_valid_slot ($slot_name)>
287
127d39a7 288This will return true if C<$slot_name> is a valid slot name.
289
da5680be 290=item B<is_dependent_on_superclasses>
291
292This method returns true when the meta instance must be recreated on any
293superclass changes.
294
295Defaults to false.
296
24869f62 297=back
298
9fa4d0b4 299=head2 Operations on Instance Structures
300
8d2d4c67 301An important distinction of this sub-protocol is that the
302instance meta-object is a different entity from the actual
303instance it creates. For this reason, any actions on slots
9fa4d0b4 304require that the C<$instance_structure> is passed into them.
24869f62 305
127d39a7 306The names of these methods pretty much explain exactly
307what they do, if that is not enough then I suggest reading
308the source, it is very straightfoward.
309
24869f62 310=over 4
311
9fa4d0b4 312=item B<get_slot_value ($instance_structure, $slot_name)>
24869f62 313
9fa4d0b4 314=item B<set_slot_value ($instance_structure, $slot_name, $value)>
315
316=item B<initialize_slot ($instance_structure, $slot_name)>
317
7d28758b 318=item B<deinitialize_slot ($instance_structure, $slot_name)>
319
9fa4d0b4 320=item B<initialize_all_slots ($instance_structure)>
321
7d28758b 322=item B<deinitialize_all_slots ($instance_structure)>
323
9fa4d0b4 324=item B<is_slot_initialized ($instance_structure, $slot_name)>
24869f62 325
ee7c0467 326=item B<weaken_slot_value ($instance_structure, $slot_name)>
327
328=item B<strengthen_slot_value ($instance_structure, $slot_name)>
329
5fdf066d 330=item B<rebless_instance_structure ($instance_structure, $new_metaclass)>
331
ee7c0467 332=back
333
334=head2 Inlineable Instance Operations
335
336=over 4
337
c0cbf4d9 338=item B<is_inlinable>
339
8d2d4c67 340Each meta-instance should override this method to tell Class::MOP if it's
127d39a7 341possible to inline the slot access. This is currently only used by
342L<Class::MOP::Immutable> when performing optimizations.
c0cbf4d9 343
495af518 344=item B<inline_create_instance>
345
ee7c0467 346=item B<inline_slot_access ($instance_structure, $slot_name)>
347
348=item B<inline_get_slot_value ($instance_structure, $slot_name)>
349
350=item B<inline_set_slot_value ($instance_structure, $slot_name, $value)>
351
352=item B<inline_initialize_slot ($instance_structure, $slot_name)>
353
7d28758b 354=item B<inline_deinitialize_slot ($instance_structure, $slot_name)>
355
ee7c0467 356=item B<inline_is_slot_initialized ($instance_structure, $slot_name)>
5582521c 357
ee7c0467 358=item B<inline_weaken_slot_value ($instance_structure, $slot_name)>
5582521c 359
ee7c0467 360=item B<inline_strengthen_slot_value ($instance_structure, $slot_name)>
5582521c 361
24869f62 362=back
363
1a09d9cc 364=head1 AUTHORS
24869f62 365
9fa4d0b4 366Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
367
24869f62 368Stevan Little E<lt>stevan@iinteractive.comE<gt>
369
370=head1 COPYRIGHT AND LICENSE
371
69e3ab0a 372Copyright 2006-2008 by Infinity Interactive, Inc.
24869f62 373
374L<http://www.iinteractive.com>
375
376This library is free software; you can redistribute it and/or modify
8d2d4c67 377it under the same terms as Perl itself.
24869f62 378
84ef30d1 379=cut
5582521c 380