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