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