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