predicate fixes
[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
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) = @_;
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) = @_;
8d2d4c67 73 $self->is_slot_initialized($instance, $slot_name) ? $instance->{$slot_name} : undef;
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) = @_;
2d711cc8 107 exists $instance->{$slot_name} ? 1 : 0;
2bab2be6 108}
839ea973 109
5582521c 110sub weaken_slot_value {
8d2d4c67 111 my ($self, $instance, $slot_name) = @_;
112 weaken $instance->{$slot_name};
5582521c 113}
114
115sub strengthen_slot_value {
8d2d4c67 116 my ($self, $instance, $slot_name) = @_;
117 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
5582521c 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) = @_;
8d2d4c67 136 'exists ' . $self->inline_slot_access($instance, $slot_name) .
137 ' ? ' . $self->inline_slot_access($instance, $slot_name) . ' : undef'
ee7c0467 138}
139
140sub inline_set_slot_value {
141 my ($self, $instance, $slot_name, $value) = @_;
8d2d4c67 142 $self->inline_slot_access($instance, $slot_name) . " = $value",
ee7c0467 143}
144
145sub inline_initialize_slot {
146 my ($self, $instance, $slot_name) = @_;
147 $self->inline_set_slot_value($instance, $slot_name, 'undef'),
148}
149
7d28758b 150sub inline_deinitialize_slot {
151 my ($self, $instance, $slot_name) = @_;
152 "delete " . $self->inline_slot_access($instance, $slot_name);
153}
ee7c0467 154sub inline_is_slot_initialized {
155 my ($self, $instance, $slot_name) = @_;
156 "exists " . $self->inline_slot_access($instance, $slot_name) . " ? 1 : 0";
157}
158
159sub inline_weaken_slot_value {
160 my ($self, $instance, $slot_name) = @_;
161 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
162}
163
164sub inline_strengthen_slot_value {
165 my ($self, $instance, $slot_name) = @_;
166 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
167}
168
24869f62 1691;
170
171__END__
172
173=pod
174
8d2d4c67 175=head1 NAME
24869f62 176
177Class::MOP::Instance - Instance Meta Object
178
179=head1 SYNOPSIS
180
8d2d4c67 181 # for the most part, this protocol is internal
182 # and not for public usage, but this how one
9fa4d0b4 183 # might use it
8d2d4c67 184
9fa4d0b4 185 package Foo;
8d2d4c67 186
9fa4d0b4 187 use strict;
188 use warnings;
1becdfcc 189 use metaclass (
9fa4d0b4 190 ':instance_metaclass' => 'ArrayBasedStorage::Instance',
191 );
8d2d4c67 192
9fa4d0b4 193 # now Foo->new produces blessed ARRAY ref based objects
194
24869f62 195=head1 DESCRIPTION
196
8d2d4c67 197This is a sub-protocol which governs instance creation
9fa4d0b4 198and access to the slots of the instance structure.
199
8d2d4c67 200This may seem like over-abstraction, but by abstracting
201this process into a sub-protocol we make it possible to
202easily switch the details of how an object's instance is
203stored with minimal impact. In most cases just subclassing
204this class will be all you need to do (see the examples;
205F<examples/ArrayBasedStorage.pod> and
1becdfcc 206F<examples/InsideOutClass.pod> for details).
9fa4d0b4 207
24869f62 208=head1 METHODS
209
210=over 4
211
9fa4d0b4 212=item B<new ($meta, @attrs)>
213
8d2d4c67 214Creates a new instance meta-object and gathers all the slots from
9fa4d0b4 215the list of C<@attrs> given.
216
217=item B<meta>
218
8d2d4c67 219This will return a B<Class::MOP::Class> instance which is related
9fa4d0b4 220to this class.
221
222=back
223
224=head2 Creation of Instances
225
226=over 4
24869f62 227
58287a97 228=item B<create_instance>
229
8d2d4c67 230This creates the appropriate structure needed for the instance and
9fa4d0b4 231then calls C<bless_instance_structure> to bless it into the class.
0e76a376 232
9fa4d0b4 233=item B<bless_instance_structure ($instance_structure)>
839ea973 234
9fa4d0b4 235This does just exactly what it says it does.
0e76a376 236
f7259199 237=item B<clone_instance ($instance_structure)>
238
9fa4d0b4 239=back
839ea973 240
9fa4d0b4 241=head2 Instrospection
58287a97 242
8d2d4c67 243NOTE: There might be more methods added to this part of the API,
9fa4d0b4 244we will add then when we need them basically.
58287a97 245
9fa4d0b4 246=over 4
247
c23184fc 248=item B<associated_metaclass>
249
9fa4d0b4 250=item B<get_all_slots>
251
8d2d4c67 252This will return the current list of slots based on what was
9fa4d0b4 253given to this object in C<new>.
58287a97 254
f7259199 255=item B<is_valid_slot ($slot_name)>
256
24869f62 257=back
258
9fa4d0b4 259=head2 Operations on Instance Structures
260
8d2d4c67 261An important distinction of this sub-protocol is that the
262instance meta-object is a different entity from the actual
263instance it creates. For this reason, any actions on slots
9fa4d0b4 264require that the C<$instance_structure> is passed into them.
24869f62 265
266=over 4
267
9fa4d0b4 268=item B<get_slot_value ($instance_structure, $slot_name)>
24869f62 269
9fa4d0b4 270=item B<set_slot_value ($instance_structure, $slot_name, $value)>
271
272=item B<initialize_slot ($instance_structure, $slot_name)>
273
7d28758b 274=item B<deinitialize_slot ($instance_structure, $slot_name)>
275
9fa4d0b4 276=item B<initialize_all_slots ($instance_structure)>
277
7d28758b 278=item B<deinitialize_all_slots ($instance_structure)>
279
9fa4d0b4 280=item B<is_slot_initialized ($instance_structure, $slot_name)>
24869f62 281
ee7c0467 282=item B<weaken_slot_value ($instance_structure, $slot_name)>
283
284=item B<strengthen_slot_value ($instance_structure, $slot_name)>
285
286=back
287
288=head2 Inlineable Instance Operations
289
8d2d4c67 290This part of the API is currently un-used. It is there for use
291in future experiments in class finailization mostly. Best to
f7259199 292ignore this for now.
293
ee7c0467 294=over 4
295
c0cbf4d9 296=item B<is_inlinable>
297
8d2d4c67 298Each meta-instance should override this method to tell Class::MOP if it's
299possible to inline the slot access.
c0cbf4d9 300
8d2d4c67 301This is currently only used by Class::MOP::Class::Immutable when performing
c0cbf4d9 302optimizations.
303
495af518 304=item B<inline_create_instance>
305
ee7c0467 306=item B<inline_slot_access ($instance_structure, $slot_name)>
307
308=item B<inline_get_slot_value ($instance_structure, $slot_name)>
309
310=item B<inline_set_slot_value ($instance_structure, $slot_name, $value)>
311
312=item B<inline_initialize_slot ($instance_structure, $slot_name)>
313
7d28758b 314=item B<inline_deinitialize_slot ($instance_structure, $slot_name)>
315
ee7c0467 316=item B<inline_is_slot_initialized ($instance_structure, $slot_name)>
5582521c 317
ee7c0467 318=item B<inline_weaken_slot_value ($instance_structure, $slot_name)>
5582521c 319
ee7c0467 320=item B<inline_strengthen_slot_value ($instance_structure, $slot_name)>
5582521c 321
24869f62 322=back
323
1a09d9cc 324=head1 AUTHORS
24869f62 325
9fa4d0b4 326Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
327
24869f62 328Stevan Little E<lt>stevan@iinteractive.comE<gt>
329
330=head1 COPYRIGHT AND LICENSE
331
2367814a 332Copyright 2006, 2007 by Infinity Interactive, Inc.
24869f62 333
334L<http://www.iinteractive.com>
335
336This library is free software; you can redistribute it and/or modify
8d2d4c67 337it under the same terms as Perl itself.
24869f62 338
84ef30d1 339=cut
5582521c 340