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