2 package Class::MOP::Instance;
7 use Scalar::Util 'weaken', 'blessed';
9 our $VERSION = '0.64_01';
10 $VERSION = eval $VERSION;
11 our $AUTHORITY = 'cpan:STEVAN';
13 use base 'Class::MOP::Object';
16 my ($class, @args) = @_;
19 unshift @args, "associated_metaclass";
20 } elsif ( @args >= 2 && blessed($args[0]) && $args[0]->isa("Class::MOP::Class") ) {
22 my ( $meta, @attrs ) = @args;
23 @args = ( associated_metaclass => $meta, attributes => \@attrs );
28 $options{slots} ||= [ map { $_->slots } @{ $options{attributes} || [] } ];
29 $options{slot_hash} = { map { $_ => undef } @{ $options{slots} } }; # FIXME lazy_build
36 my $options = $class->BUILDARGS(@_);
38 # FIXME replace with a proper constructor
39 my $instance = $class->_new(%$options);
41 # FIXME weak_ref => 1,
42 weaken($instance->{'associated_metaclass'});
48 my ( $class, %options ) = @_;
51 # I am not sure that it makes
52 # sense to pass in the meta
53 # The ideal would be to just
54 # pass in the class name, but
55 # that is placing too much of
56 # an assumption on bless(),
57 # which is *probably* a safe
58 # assumption,.. but you can
60 'associated_metaclass' => $options{associated_metaclass},
61 'attributes' => $options{attributes},
62 'slots' => $options{slots},
63 'slot_hash' => $options{slot_hash},
67 sub _class_name { $_[0]->{_class_name} ||= $_[0]->associated_metaclass->name }
69 sub associated_metaclass { $_[0]{'associated_metaclass'} }
73 bless {}, $self->_class_name;
77 sub bless_instance_structure {
78 my ($self, $instance_structure) = @_;
79 bless $instance_structure, $self->_class_name;
83 my ($self, $instance) = @_;
84 bless { %$instance }, $self->_class_name;
87 # operations on meta instance
91 return @{$self->{'slots'}};
95 my ($self, $slot_name) = @_;
96 exists $self->{'slot_hash'}->{$slot_name};
99 # operations on created instances
102 my ($self, $instance, $slot_name) = @_;
103 $instance->{$slot_name};
107 my ($self, $instance, $slot_name, $value) = @_;
108 $instance->{$slot_name} = $value;
111 sub initialize_slot {
112 my ($self, $instance, $slot_name) = @_;
116 sub deinitialize_slot {
117 my ( $self, $instance, $slot_name ) = @_;
118 delete $instance->{$slot_name};
121 sub initialize_all_slots {
122 my ($self, $instance) = @_;
123 foreach my $slot_name ($self->get_all_slots) {
124 $self->initialize_slot($instance, $slot_name);
128 sub deinitialize_all_slots {
129 my ($self, $instance) = @_;
130 foreach my $slot_name ($self->get_all_slots) {
131 $self->deinitialize_slot($instance, $slot_name);
135 sub is_slot_initialized {
136 my ($self, $instance, $slot_name, $value) = @_;
137 exists $instance->{$slot_name};
140 sub weaken_slot_value {
141 my ($self, $instance, $slot_name) = @_;
142 weaken $instance->{$slot_name};
145 sub strengthen_slot_value {
146 my ($self, $instance, $slot_name) = @_;
147 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
150 sub rebless_instance_structure {
151 my ($self, $instance, $metaclass) = @_;
152 bless $instance, $metaclass->name;
155 sub is_dependent_on_superclasses {
156 return; # for meta instances that require updates on inherited slot changes
159 # inlinable operation snippets
161 sub is_inlinable { 1 }
163 sub inline_create_instance {
164 my ($self, $class_variable) = @_;
165 'bless {} => ' . $class_variable;
168 sub inline_slot_access {
169 my ($self, $instance, $slot_name) = @_;
170 sprintf "%s->{%s}", $instance, $slot_name;
173 sub inline_get_slot_value {
174 my ($self, $instance, $slot_name) = @_;
175 $self->inline_slot_access($instance, $slot_name);
178 sub inline_set_slot_value {
179 my ($self, $instance, $slot_name, $value) = @_;
180 $self->inline_slot_access($instance, $slot_name) . " = $value",
183 sub inline_initialize_slot {
184 my ($self, $instance, $slot_name) = @_;
188 sub inline_deinitialize_slot {
189 my ($self, $instance, $slot_name) = @_;
190 "delete " . $self->inline_slot_access($instance, $slot_name);
192 sub inline_is_slot_initialized {
193 my ($self, $instance, $slot_name) = @_;
194 "exists " . $self->inline_slot_access($instance, $slot_name);
197 sub inline_weaken_slot_value {
198 my ($self, $instance, $slot_name) = @_;
199 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
202 sub inline_strengthen_slot_value {
203 my ($self, $instance, $slot_name) = @_;
204 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
215 Class::MOP::Instance - Instance Meta Object
219 The meta instance is used by attributes for low level storage.
221 Using this API generally violates attribute encapsulation and is not
222 recommended, instead look at L<Class::MOP::Attribute/get_value>,
223 L<Class::MOP::Attribute/set_value> for the recommended way to fiddle with
224 attribute values in a generic way, independent of how/whether accessors have
225 been defined. Accessors can be found using L<Class::MOP::Class/get_attribute>.
227 This may seem like over-abstraction, but by abstracting
228 this process into a sub-protocol we make it possible to
229 easily switch the details of how an object's instance is
230 stored with minimal impact. In most cases just subclassing
231 this class will be all you need to do (see the examples;
232 F<examples/ArrayBasedStorage.pod> and
233 F<examples/InsideOutClass.pod> for details).
241 Creates a new instance meta-object and gathers all the slots from
242 the list of C<@attrs> given.
246 Processes arguments for compatibility.
250 Returns the metaclass of L<Class::MOP::Instance>.
254 =head2 Creation of Instances
258 =item B<create_instance>
260 This creates the appropriate structure needed for the instance and blesses it.
262 =item B<bless_instance_structure ($instance_structure)>
264 This does just exactly what it says it does.
266 This method has been deprecated but remains for compatibility reasons. None of
267 the subclasses of L<Class::MOP::Instance> ever bothered to actually make use of
268 it, so it was deemed unnecessary fluff.
270 =item B<clone_instance ($instance_structure)>
272 Creates a shallow clone of $instance_structure.
278 NOTE: There might be more methods added to this part of the API,
279 we will add then when we need them basically.
283 =item B<associated_metaclass>
285 This returns the metaclass associated with this instance.
287 =item B<get_all_slots>
289 This will return the current list of slots based on what was
290 given to this object in C<new>.
292 =item B<is_valid_slot ($slot_name)>
294 This will return true if C<$slot_name> is a valid slot name.
296 =item B<is_dependent_on_superclasses>
298 This method returns true when the meta instance must be recreated on any
305 =head2 Operations on Instance Structures
307 An important distinction of this sub-protocol is that the
308 instance meta-object is a different entity from the actual
309 instance it creates. For this reason, any actions on slots
310 require that the C<$instance_structure> is passed into them.
312 The names of these methods pretty much explain exactly
313 what they do, if that is not enough then I suggest reading
314 the source, it is very straightfoward.
318 =item B<get_slot_value ($instance_structure, $slot_name)>
320 =item B<set_slot_value ($instance_structure, $slot_name, $value)>
322 =item B<initialize_slot ($instance_structure, $slot_name)>
324 =item B<deinitialize_slot ($instance_structure, $slot_name)>
326 =item B<initialize_all_slots ($instance_structure)>
328 =item B<deinitialize_all_slots ($instance_structure)>
330 =item B<is_slot_initialized ($instance_structure, $slot_name)>
332 =item B<weaken_slot_value ($instance_structure, $slot_name)>
334 =item B<strengthen_slot_value ($instance_structure, $slot_name)>
336 =item B<rebless_instance_structure ($instance_structure, $new_metaclass)>
340 =head2 Inlineable Instance Operations
344 =item B<is_inlinable>
346 Each meta-instance should override this method to tell Class::MOP if it's
347 possible to inline the slot access. This is currently only used by
348 L<Class::MOP::Immutable> when performing optimizations.
350 =item B<inline_create_instance>
352 =item B<inline_slot_access ($instance_structure, $slot_name)>
354 =item B<inline_get_slot_value ($instance_structure, $slot_name)>
356 =item B<inline_set_slot_value ($instance_structure, $slot_name, $value)>
358 =item B<inline_initialize_slot ($instance_structure, $slot_name)>
360 =item B<inline_deinitialize_slot ($instance_structure, $slot_name)>
362 =item B<inline_is_slot_initialized ($instance_structure, $slot_name)>
364 =item B<inline_weaken_slot_value ($instance_structure, $slot_name)>
366 =item B<inline_strengthen_slot_value ($instance_structure, $slot_name)>
372 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
374 Stevan Little E<lt>stevan@iinteractive.comE<gt>
376 =head1 COPYRIGHT AND LICENSE
378 Copyright 2006-2008 by Infinity Interactive, Inc.
380 L<http://www.iinteractive.com>
382 This library is free software; you can redistribute it and/or modify
383 it under the same terms as Perl itself.