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