tweak the initializer args, document set_initial_value
[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
0ab65f99 81sub _set_initial_slot_value {
82 my ($self, $instance, $slot_name, $value, $initializer) = @_;
83
84 return $self->set_slot_value($instance, $slot_name, $value)
85 unless $initializer;
86
87 my $callback = sub {
88 $self->set_slot_value($instance, $slot_name, $_[0]);
89 };
90
91 # most things will just want to set a value, so make it first arg
c0921932 92 $instance->$initializer($value, $callback, $self);
0ab65f99 93}
94
2d711cc8 95sub initialize_slot {
49c93440 96 my ($self, $instance, $slot_name) = @_;
8d2d4c67 97 #$self->set_slot_value($instance, $slot_name, undef);
2d711cc8 98}
99
7d28758b 100sub deinitialize_slot {
101 my ( $self, $instance, $slot_name ) = @_;
102 delete $instance->{$slot_name};
103}
104
c174112e 105sub initialize_all_slots {
106 my ($self, $instance) = @_;
107 foreach my $slot_name ($self->get_all_slots) {
108 $self->initialize_slot($instance, $slot_name);
109 }
110}
111
7d28758b 112sub deinitialize_all_slots {
113 my ($self, $instance) = @_;
114 foreach my $slot_name ($self->get_all_slots) {
115 $self->deinitialize_slot($instance, $slot_name);
116 }
117}
118
49c93440 119sub is_slot_initialized {
120 my ($self, $instance, $slot_name, $value) = @_;
230472a7 121 exists $instance->{$slot_name};
2bab2be6 122}
839ea973 123
5582521c 124sub weaken_slot_value {
69e3ab0a 125 my ($self, $instance, $slot_name) = @_;
126 weaken $instance->{$slot_name};
5582521c 127}
128
129sub strengthen_slot_value {
69e3ab0a 130 my ($self, $instance, $slot_name) = @_;
131 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
5582521c 132}
133
3d9e4646 134sub rebless_instance_structure {
135 my ($self, $instance, $metaclass) = @_;
136 bless $instance, $metaclass->name;
137}
138
ee7c0467 139# inlinable operation snippets
140
c0cbf4d9 141sub is_inlinable { 1 }
142
143sub inline_create_instance {
144 my ($self, $class_variable) = @_;
145 'bless {} => ' . $class_variable;
146}
147
ee7c0467 148sub inline_slot_access {
149 my ($self, $instance, $slot_name) = @_;
150 sprintf "%s->{%s}", $instance, $slot_name;
151}
152
153sub inline_get_slot_value {
154 my ($self, $instance, $slot_name) = @_;
230472a7 155 $self->inline_slot_access($instance, $slot_name);
ee7c0467 156}
157
158sub inline_set_slot_value {
159 my ($self, $instance, $slot_name, $value) = @_;
8d2d4c67 160 $self->inline_slot_access($instance, $slot_name) . " = $value",
ee7c0467 161}
162
163sub inline_initialize_slot {
164 my ($self, $instance, $slot_name) = @_;
165 $self->inline_set_slot_value($instance, $slot_name, 'undef'),
166}
167
7d28758b 168sub inline_deinitialize_slot {
169 my ($self, $instance, $slot_name) = @_;
170 "delete " . $self->inline_slot_access($instance, $slot_name);
171}
ee7c0467 172sub inline_is_slot_initialized {
173 my ($self, $instance, $slot_name) = @_;
230472a7 174 "exists " . $self->inline_slot_access($instance, $slot_name);
ee7c0467 175}
176
177sub inline_weaken_slot_value {
178 my ($self, $instance, $slot_name) = @_;
179 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
180}
181
182sub inline_strengthen_slot_value {
183 my ($self, $instance, $slot_name) = @_;
184 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
185}
186
24869f62 1871;
188
189__END__
190
191=pod
192
8d2d4c67 193=head1 NAME
24869f62 194
195Class::MOP::Instance - Instance Meta Object
196
197=head1 SYNOPSIS
198
bc9e7815 199 # This API is largely internal
200 # you shouldn't need it unless you are writing meta attributes or meta
201 # instances
9fa4d0b4 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
208reccomended, instead look at L<Class::MOP::Attribute/get_value>,
209L<Class::MOP::Attribute/set_value> for the reccomended way to fiddle with
210attribute values in a generic way, independant of how/whether accessors have
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
9fa4d0b4 225=item B<new ($meta, @attrs)>
226
8d2d4c67 227Creates a new instance meta-object and gathers all the slots from
9fa4d0b4 228the list of C<@attrs> given.
229
230=item B<meta>
231
8d2d4c67 232This will return a B<Class::MOP::Class> instance which is related
9fa4d0b4 233to this class.
234
235=back
236
237=head2 Creation of Instances
238
239=over 4
24869f62 240
58287a97 241=item B<create_instance>
242
8d2d4c67 243This creates the appropriate structure needed for the instance and
9fa4d0b4 244then calls C<bless_instance_structure> to bless it into the class.
0e76a376 245
9fa4d0b4 246=item B<bless_instance_structure ($instance_structure)>
839ea973 247
9fa4d0b4 248This does just exactly what it says it does.
0e76a376 249
f7259199 250=item B<clone_instance ($instance_structure)>
251
9fa4d0b4 252=back
839ea973 253
9fa4d0b4 254=head2 Instrospection
58287a97 255
8d2d4c67 256NOTE: There might be more methods added to this part of the API,
9fa4d0b4 257we will add then when we need them basically.
58287a97 258
9fa4d0b4 259=over 4
260
c23184fc 261=item B<associated_metaclass>
262
9fa4d0b4 263=item B<get_all_slots>
264
8d2d4c67 265This will return the current list of slots based on what was
9fa4d0b4 266given to this object in C<new>.
58287a97 267
f7259199 268=item B<is_valid_slot ($slot_name)>
269
24869f62 270=back
271
9fa4d0b4 272=head2 Operations on Instance Structures
273
8d2d4c67 274An important distinction of this sub-protocol is that the
275instance meta-object is a different entity from the actual
276instance it creates. For this reason, any actions on slots
9fa4d0b4 277require that the C<$instance_structure> is passed into them.
24869f62 278
279=over 4
280
9fa4d0b4 281=item B<get_slot_value ($instance_structure, $slot_name)>
24869f62 282
9fa4d0b4 283=item B<set_slot_value ($instance_structure, $slot_name, $value)>
284
285=item B<initialize_slot ($instance_structure, $slot_name)>
286
7d28758b 287=item B<deinitialize_slot ($instance_structure, $slot_name)>
288
9fa4d0b4 289=item B<initialize_all_slots ($instance_structure)>
290
7d28758b 291=item B<deinitialize_all_slots ($instance_structure)>
292
9fa4d0b4 293=item B<is_slot_initialized ($instance_structure, $slot_name)>
24869f62 294
ee7c0467 295=item B<weaken_slot_value ($instance_structure, $slot_name)>
296
297=item B<strengthen_slot_value ($instance_structure, $slot_name)>
298
5fdf066d 299=item B<rebless_instance_structure ($instance_structure, $new_metaclass)>
300
ee7c0467 301=back
302
303=head2 Inlineable Instance Operations
304
8d2d4c67 305This part of the API is currently un-used. It is there for use
306in future experiments in class finailization mostly. Best to
f7259199 307ignore this for now.
308
ee7c0467 309=over 4
310
c0cbf4d9 311=item B<is_inlinable>
312
8d2d4c67 313Each meta-instance should override this method to tell Class::MOP if it's
314possible to inline the slot access.
c0cbf4d9 315
8d2d4c67 316This is currently only used by Class::MOP::Class::Immutable when performing
c0cbf4d9 317optimizations.
318
495af518 319=item B<inline_create_instance>
320
ee7c0467 321=item B<inline_slot_access ($instance_structure, $slot_name)>
322
323=item B<inline_get_slot_value ($instance_structure, $slot_name)>
324
325=item B<inline_set_slot_value ($instance_structure, $slot_name, $value)>
326
327=item B<inline_initialize_slot ($instance_structure, $slot_name)>
328
7d28758b 329=item B<inline_deinitialize_slot ($instance_structure, $slot_name)>
330
ee7c0467 331=item B<inline_is_slot_initialized ($instance_structure, $slot_name)>
5582521c 332
ee7c0467 333=item B<inline_weaken_slot_value ($instance_structure, $slot_name)>
5582521c 334
ee7c0467 335=item B<inline_strengthen_slot_value ($instance_structure, $slot_name)>
5582521c 336
24869f62 337=back
338
1a09d9cc 339=head1 AUTHORS
24869f62 340
9fa4d0b4 341Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
342
24869f62 343Stevan Little E<lt>stevan@iinteractive.comE<gt>
344
345=head1 COPYRIGHT AND LICENSE
346
69e3ab0a 347Copyright 2006-2008 by Infinity Interactive, Inc.
24869f62 348
349L<http://www.iinteractive.com>
350
351This library is free software; you can redistribute it and/or modify
8d2d4c67 352it under the same terms as Perl itself.
24869f62 353
84ef30d1 354=cut
5582521c 355