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