2 package Class::MOP::Instance;
7 use Scalar::Util 'weaken', 'blessed';
10 our $AUTHORITY = 'cpan:STEVAN';
13 require Class::MOP::Class;
14 Class::MOP::Class->initialize(blessed($_[0]) || $_[0]);
18 my ($class, $meta, @attrs) = @_;
19 my @slots = map { $_->slots } @attrs;
20 my $instance = bless {
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
32 '@!slots' => { map { $_ => undef } @slots },
35 weaken($instance->{'$!meta'});
40 sub associated_metaclass { (shift)->{'$!meta'} }
44 $self->bless_instance_structure({});
47 sub bless_instance_structure {
48 my ($self, $instance_structure) = @_;
49 bless $instance_structure, $self->associated_metaclass->name;
53 my ($self, $instance) = @_;
54 $self->bless_instance_structure({ %$instance });
57 # operations on meta instance
61 return keys %{$self->{'@!slots'}};
65 my ($self, $slot_name) = @_;
66 exists $self->{'@!slots'}->{$slot_name} ? 1 : 0;
69 # operations on created instances
72 my ($self, $instance, $slot_name) = @_;
73 $self->is_slot_initialized($instance, $slot_name) ? $instance->{$slot_name} : undef;
77 my ($self, $instance, $slot_name, $value) = @_;
78 $instance->{$slot_name} = $value;
82 my ($self, $instance, $slot_name) = @_;
83 #$self->set_slot_value($instance, $slot_name, undef);
86 sub deinitialize_slot {
87 my ( $self, $instance, $slot_name ) = @_;
88 delete $instance->{$slot_name};
91 sub initialize_all_slots {
92 my ($self, $instance) = @_;
93 foreach my $slot_name ($self->get_all_slots) {
94 $self->initialize_slot($instance, $slot_name);
98 sub deinitialize_all_slots {
99 my ($self, $instance) = @_;
100 foreach my $slot_name ($self->get_all_slots) {
101 $self->deinitialize_slot($instance, $slot_name);
105 sub is_slot_initialized {
106 my ($self, $instance, $slot_name, $value) = @_;
107 exists $instance->{$slot_name} ? 1 : 0;
110 sub weaken_slot_value {
111 my ($self, $instance, $slot_name) = @_;
112 weaken $instance->{$slot_name};
115 sub strengthen_slot_value {
116 my ($self, $instance, $slot_name) = @_;
117 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
120 sub rebless_instance_structure {
121 my ($self, $instance, $metaclass) = @_;
122 bless $instance, $metaclass->name;
125 sub get_all_slot_values {
126 my ($self, $instance) = @_;
127 my $class = $self->associated_metaclass;
130 for my $attr ($class->compute_all_applicable_attributes) {
131 my $name = $attr->name;
132 $map{$name} = $self->get_slot_value($instance, $name)
133 if $self->is_slot_initialized($instance, $name);
139 # inlinable operation snippets
141 sub is_inlinable { 1 }
143 sub inline_create_instance {
144 my ($self, $class_variable) = @_;
145 'bless {} => ' . $class_variable;
148 sub inline_slot_access {
149 my ($self, $instance, $slot_name) = @_;
150 sprintf "%s->{%s}", $instance, $slot_name;
153 sub inline_get_slot_value {
154 my ($self, $instance, $slot_name) = @_;
155 'exists ' . $self->inline_slot_access($instance, $slot_name) .
156 ' ? ' . $self->inline_slot_access($instance, $slot_name) . ' : undef'
159 sub inline_set_slot_value {
160 my ($self, $instance, $slot_name, $value) = @_;
161 $self->inline_slot_access($instance, $slot_name) . " = $value",
164 sub inline_initialize_slot {
165 my ($self, $instance, $slot_name) = @_;
166 $self->inline_set_slot_value($instance, $slot_name, 'undef'),
169 sub inline_deinitialize_slot {
170 my ($self, $instance, $slot_name) = @_;
171 "delete " . $self->inline_slot_access($instance, $slot_name);
173 sub inline_is_slot_initialized {
174 my ($self, $instance, $slot_name) = @_;
175 "exists " . $self->inline_slot_access($instance, $slot_name) . " ? 1 : 0";
178 sub inline_weaken_slot_value {
179 my ($self, $instance, $slot_name) = @_;
180 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
183 sub inline_strengthen_slot_value {
184 my ($self, $instance, $slot_name) = @_;
185 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
196 Class::MOP::Instance - Instance Meta Object
200 # for the most part, this protocol is internal
201 # and not for public usage, but this how one
209 ':instance_metaclass' => 'ArrayBasedStorage::Instance',
212 # now Foo->new produces blessed ARRAY ref based objects
216 This is a sub-protocol which governs instance creation
217 and access to the slots of the instance structure.
219 This may seem like over-abstraction, but by abstracting
220 this process into a sub-protocol we make it possible to
221 easily switch the details of how an object's instance is
222 stored with minimal impact. In most cases just subclassing
223 this class will be all you need to do (see the examples;
224 F<examples/ArrayBasedStorage.pod> and
225 F<examples/InsideOutClass.pod> for details).
231 =item B<new ($meta, @attrs)>
233 Creates a new instance meta-object and gathers all the slots from
234 the list of C<@attrs> given.
238 This will return a B<Class::MOP::Class> instance which is related
243 =head2 Creation of Instances
247 =item B<create_instance>
249 This creates the appropriate structure needed for the instance and
250 then calls C<bless_instance_structure> to bless it into the class.
252 =item B<bless_instance_structure ($instance_structure)>
254 This does just exactly what it says it does.
256 =item B<clone_instance ($instance_structure)>
260 =head2 Instrospection
262 NOTE: There might be more methods added to this part of the API,
263 we will add then when we need them basically.
267 =item B<associated_metaclass>
269 =item B<get_all_slots>
271 This will return the current list of slots based on what was
272 given to this object in C<new>.
274 =item B<is_valid_slot ($slot_name)>
278 =head2 Operations on Instance Structures
280 An important distinction of this sub-protocol is that the
281 instance meta-object is a different entity from the actual
282 instance it creates. For this reason, any actions on slots
283 require that the C<$instance_structure> is passed into them.
287 =item B<get_slot_value ($instance_structure, $slot_name)>
289 =item B<set_slot_value ($instance_structure, $slot_name, $value)>
291 =item B<get_all_slot_values ($instance_structure)>
293 =item B<initialize_slot ($instance_structure, $slot_name)>
295 =item B<deinitialize_slot ($instance_structure, $slot_name)>
297 =item B<initialize_all_slots ($instance_structure)>
299 =item B<deinitialize_all_slots ($instance_structure)>
301 =item B<is_slot_initialized ($instance_structure, $slot_name)>
303 =item B<weaken_slot_value ($instance_structure, $slot_name)>
305 =item B<strengthen_slot_value ($instance_structure, $slot_name)>
307 =item B<rebless_instance_structure ($instance_structure, $new_metaclass)>
311 =head2 Inlineable Instance Operations
313 This part of the API is currently un-used. It is there for use
314 in future experiments in class finailization mostly. Best to
319 =item B<is_inlinable>
321 Each meta-instance should override this method to tell Class::MOP if it's
322 possible to inline the slot access.
324 This is currently only used by Class::MOP::Class::Immutable when performing
327 =item B<inline_create_instance>
329 =item B<inline_slot_access ($instance_structure, $slot_name)>
331 =item B<inline_get_slot_value ($instance_structure, $slot_name)>
333 =item B<inline_set_slot_value ($instance_structure, $slot_name, $value)>
335 =item B<inline_initialize_slot ($instance_structure, $slot_name)>
337 =item B<inline_deinitialize_slot ($instance_structure, $slot_name)>
339 =item B<inline_is_slot_initialized ($instance_structure, $slot_name)>
341 =item B<inline_weaken_slot_value ($instance_structure, $slot_name)>
343 =item B<inline_strengthen_slot_value ($instance_structure, $slot_name)>
349 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
351 Stevan Little E<lt>stevan@iinteractive.comE<gt>
353 =head1 COPYRIGHT AND LICENSE
355 Copyright 2006-2008 by Infinity Interactive, Inc.
357 L<http://www.iinteractive.com>
359 This library is free software; you can redistribute it and/or modify
360 it under the same terms as Perl itself.