tweaking the attribute initializer stuff a little
[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
0c6f4c4a 9our $VERSION = '0.04';
f0480c45 10our $AUTHORITY = 'cpan:STEVAN';
24869f62 11
8d2d4c67 12sub meta {
24869f62 13 require Class::MOP::Class;
14 Class::MOP::Class->initialize(blessed($_[0]) || $_[0]);
15}
16
8d2d4c67 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
8d2d4c67 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(),
fc3ddd1d 28 # which is *probably* a safe
8d2d4c67 29 # assumption,.. but you can
fc3ddd1d 30 # never tell <:)
c23184fc 31 '$!meta' => $meta,
32 '@!slots' => { map { $_ => undef } @slots },
8d2d4c67 33 } => $class;
34
c23184fc 35 weaken($instance->{'$!meta'});
8d2d4c67 36
c23184fc 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) = @_;
230472a7 66 exists $self->{'@!slots'}->{$slot_name};
839ea973 67}
68
2d711cc8 69# operations on created instances
70
839ea973 71sub get_slot_value {
2bab2be6 72 my ($self, $instance, $slot_name) = @_;
230472a7 73 $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) = @_;
8d2d4c67 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) = @_;
230472a7 107 exists $instance->{$slot_name};
2bab2be6 108}
839ea973 109
5582521c 110sub weaken_slot_value {
69e3ab0a 111 my ($self, $instance, $slot_name) = @_;
112 weaken $instance->{$slot_name};
5582521c 113}
114
115sub strengthen_slot_value {
69e3ab0a 116 my ($self, $instance, $slot_name) = @_;
117 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
5582521c 118}
119
3d9e4646 120sub rebless_instance_structure {
121 my ($self, $instance, $metaclass) = @_;
122 bless $instance, $metaclass->name;
123}
124
ee7c0467 125# inlinable operation snippets
126
c0cbf4d9 127sub is_inlinable { 1 }
128
129sub inline_create_instance {
130 my ($self, $class_variable) = @_;
131 'bless {} => ' . $class_variable;
132}
133
ee7c0467 134sub inline_slot_access {
135 my ($self, $instance, $slot_name) = @_;
136 sprintf "%s->{%s}", $instance, $slot_name;
137}
138
139sub inline_get_slot_value {
140 my ($self, $instance, $slot_name) = @_;
230472a7 141 $self->inline_slot_access($instance, $slot_name);
ee7c0467 142}
143
144sub inline_set_slot_value {
145 my ($self, $instance, $slot_name, $value) = @_;
8d2d4c67 146 $self->inline_slot_access($instance, $slot_name) . " = $value",
ee7c0467 147}
148
149sub inline_initialize_slot {
150 my ($self, $instance, $slot_name) = @_;
151 $self->inline_set_slot_value($instance, $slot_name, 'undef'),
152}
153
7d28758b 154sub inline_deinitialize_slot {
155 my ($self, $instance, $slot_name) = @_;
156 "delete " . $self->inline_slot_access($instance, $slot_name);
157}
ee7c0467 158sub inline_is_slot_initialized {
159 my ($self, $instance, $slot_name) = @_;
230472a7 160 "exists " . $self->inline_slot_access($instance, $slot_name);
ee7c0467 161}
162
163sub inline_weaken_slot_value {
164 my ($self, $instance, $slot_name) = @_;
165 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
166}
167
168sub inline_strengthen_slot_value {
169 my ($self, $instance, $slot_name) = @_;
170 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
171}
172
24869f62 1731;
174
175__END__
176
177=pod
178
8d2d4c67 179=head1 NAME
24869f62 180
181Class::MOP::Instance - Instance Meta Object
182
183=head1 SYNOPSIS
184
bc9e7815 185 # This API is largely internal
186 # you shouldn't need it unless you are writing meta attributes or meta
187 # instances
9fa4d0b4 188
24869f62 189=head1 DESCRIPTION
190
bc9e7815 191The meta instance is used by attributes for low level storage.
192
193Using this API generally violates attribute encapsulation and is not
194reccomended, instead look at L<Class::MOP::Attribute/get_value>,
195L<Class::MOP::Attribute/set_value> for the reccomended way to fiddle with
196attribute values in a generic way, independant of how/whether accessors have
197been defined. Accessors can be found using L<Class::MOP::Class/get_attribute>.
9fa4d0b4 198
8d2d4c67 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
203this class will be all you need to do (see the examples;
204F<examples/ArrayBasedStorage.pod> and
1becdfcc 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
8d2d4c67 213Creates a new instance meta-object and gathers all the slots from
9fa4d0b4 214the list of C<@attrs> given.
215
216=item B<meta>
217
8d2d4c67 218This will return a B<Class::MOP::Class> instance which is related
9fa4d0b4 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
8d2d4c67 229This creates the appropriate structure needed for the instance and
9fa4d0b4 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
8d2d4c67 242NOTE: There might be more methods added to this part of the API,
9fa4d0b4 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
8d2d4c67 251This will return the current list of slots based on what was
9fa4d0b4 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
8d2d4c67 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
9fa4d0b4 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
5fdf066d 285=item B<rebless_instance_structure ($instance_structure, $new_metaclass)>
286
ee7c0467 287=back
288
289=head2 Inlineable Instance Operations
290
8d2d4c67 291This part of the API is currently un-used. It is there for use
292in future experiments in class finailization mostly. Best to
f7259199 293ignore this for now.
294
ee7c0467 295=over 4
296
c0cbf4d9 297=item B<is_inlinable>
298
8d2d4c67 299Each meta-instance should override this method to tell Class::MOP if it's
300possible to inline the slot access.
c0cbf4d9 301
8d2d4c67 302This is currently only used by Class::MOP::Class::Immutable when performing
c0cbf4d9 303optimizations.
304
495af518 305=item B<inline_create_instance>
306
ee7c0467 307=item B<inline_slot_access ($instance_structure, $slot_name)>
308
309=item B<inline_get_slot_value ($instance_structure, $slot_name)>
310
311=item B<inline_set_slot_value ($instance_structure, $slot_name, $value)>
312
313=item B<inline_initialize_slot ($instance_structure, $slot_name)>
314
7d28758b 315=item B<inline_deinitialize_slot ($instance_structure, $slot_name)>
316
ee7c0467 317=item B<inline_is_slot_initialized ($instance_structure, $slot_name)>
5582521c 318
ee7c0467 319=item B<inline_weaken_slot_value ($instance_structure, $slot_name)>
5582521c 320
ee7c0467 321=item B<inline_strengthen_slot_value ($instance_structure, $slot_name)>
5582521c 322
24869f62 323=back
324
1a09d9cc 325=head1 AUTHORS
24869f62 326
9fa4d0b4 327Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
328
24869f62 329Stevan Little E<lt>stevan@iinteractive.comE<gt>
330
331=head1 COPYRIGHT AND LICENSE
332
69e3ab0a 333Copyright 2006-2008 by Infinity Interactive, Inc.
24869f62 334
335L<http://www.iinteractive.com>
336
337This library is free software; you can redistribute it and/or modify
8d2d4c67 338it under the same terms as Perl itself.
24869f62 339
84ef30d1 340=cut
5582521c 341