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