2 package Class::MOP::Instance;
7 use Scalar::Util 'weaken', 'blessed';
10 our $AUTHORITY = 'cpan:STEVAN';
12 use base 'Class::MOP::Object';
15 my ($class, @args) = @_;
18 unshift @args, "associated_metaclass";
19 } elsif ( @args >= 2 && blessed($args[0]) && $args[0]->isa("Class::MOP::Class") ) {
21 my ( $meta, @attrs ) = @args;
22 @args = ( associated_metaclass => $meta, attributes => \@attrs );
27 $options{slots} ||= [ map { $_->slots } @{ $options{attributes} || [] } ];
28 $options{slot_hash} = { map { $_ => undef } @{ $options{slots} } }; # FIXME lazy_build
35 my $options = $class->BUILDARGS(@_);
37 # FIXME replace with a proper constructor
38 my $instance = bless {
40 # I am not sure that it makes
41 # sense to pass in the meta
42 # The ideal would be to just
43 # pass in the class name, but
44 # that is placing too much of
45 # an assumption on bless(),
46 # which is *probably* a safe
47 # assumption,.. but you can
49 'associated_metaclass' => $options->{associated_metaclass},
50 'attributes' => $options->{attributes},
51 'slots' => $options->{slots},
52 'slot_hash' => $options->{slot_hash},
55 # FIXME weak_ref => 1,
56 weaken($instance->{'associated_metaclass'});
61 sub associated_metaclass { (shift)->{'associated_metaclass'} }
65 $self->bless_instance_structure({});
68 sub bless_instance_structure {
69 my ($self, $instance_structure) = @_;
70 bless $instance_structure, $self->associated_metaclass->name;
74 my ($self, $instance) = @_;
75 $self->bless_instance_structure({ %$instance });
78 # operations on meta instance
82 return @{$self->{'slots'}};
86 my ($self, $slot_name) = @_;
87 exists $self->{'slot_hash'}->{$slot_name};
90 # operations on created instances
93 my ($self, $instance, $slot_name) = @_;
94 $instance->{$slot_name};
98 my ($self, $instance, $slot_name, $value) = @_;
99 $instance->{$slot_name} = $value;
102 sub initialize_slot {
103 my ($self, $instance, $slot_name) = @_;
107 sub deinitialize_slot {
108 my ( $self, $instance, $slot_name ) = @_;
109 delete $instance->{$slot_name};
112 sub initialize_all_slots {
113 my ($self, $instance) = @_;
114 foreach my $slot_name ($self->get_all_slots) {
115 $self->initialize_slot($instance, $slot_name);
119 sub deinitialize_all_slots {
120 my ($self, $instance) = @_;
121 foreach my $slot_name ($self->get_all_slots) {
122 $self->deinitialize_slot($instance, $slot_name);
126 sub is_slot_initialized {
127 my ($self, $instance, $slot_name, $value) = @_;
128 exists $instance->{$slot_name};
131 sub weaken_slot_value {
132 my ($self, $instance, $slot_name) = @_;
133 weaken $instance->{$slot_name};
136 sub strengthen_slot_value {
137 my ($self, $instance, $slot_name) = @_;
138 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
141 sub rebless_instance_structure {
142 my ($self, $instance, $metaclass) = @_;
143 bless $instance, $metaclass->name;
146 sub is_dependent_on_superclasses {
147 return; # for meta instances that require updates on inherited slot changes
150 # inlinable operation snippets
152 sub is_inlinable { 1 }
154 sub inline_create_instance {
155 my ($self, $class_variable) = @_;
156 'bless {} => ' . $class_variable;
159 sub inline_slot_access {
160 my ($self, $instance, $slot_name) = @_;
161 sprintf "%s->{%s}", $instance, $slot_name;
164 sub inline_get_slot_value {
165 my ($self, $instance, $slot_name) = @_;
166 $self->inline_slot_access($instance, $slot_name);
169 sub inline_set_slot_value {
170 my ($self, $instance, $slot_name, $value) = @_;
171 $self->inline_slot_access($instance, $slot_name) . " = $value",
174 sub inline_initialize_slot {
175 my ($self, $instance, $slot_name) = @_;
179 sub inline_deinitialize_slot {
180 my ($self, $instance, $slot_name) = @_;
181 "delete " . $self->inline_slot_access($instance, $slot_name);
183 sub inline_is_slot_initialized {
184 my ($self, $instance, $slot_name) = @_;
185 "exists " . $self->inline_slot_access($instance, $slot_name);
188 sub inline_weaken_slot_value {
189 my ($self, $instance, $slot_name) = @_;
190 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
193 sub inline_strengthen_slot_value {
194 my ($self, $instance, $slot_name) = @_;
195 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
206 Class::MOP::Instance - Instance Meta Object
210 The meta instance is used by attributes for low level storage.
212 Using this API generally violates attribute encapsulation and is not
213 recommended, instead look at L<Class::MOP::Attribute/get_value>,
214 L<Class::MOP::Attribute/set_value> for the recommended way to fiddle with
215 attribute values in a generic way, independent of how/whether accessors have
216 been defined. Accessors can be found using L<Class::MOP::Class/get_attribute>.
218 This may seem like over-abstraction, but by abstracting
219 this process into a sub-protocol we make it possible to
220 easily switch the details of how an object's instance is
221 stored with minimal impact. In most cases just subclassing
222 this class will be all you need to do (see the examples;
223 F<examples/ArrayBasedStorage.pod> and
224 F<examples/InsideOutClass.pod> for details).
232 Creates a new instance meta-object and gathers all the slots from
233 the list of C<@attrs> given.
237 Processes arguments for compatibility.
241 Returns the metaclass of L<Class::MOP::Instance>.
245 =head2 Creation of Instances
249 =item B<create_instance>
251 This creates the appropriate structure needed for the instance and
252 then calls C<bless_instance_structure> to bless it into the class.
254 =item B<bless_instance_structure ($instance_structure)>
256 This does just exactly what it says it does.
258 =item B<clone_instance ($instance_structure)>
260 This too does just exactly what it says it does.
266 NOTE: There might be more methods added to this part of the API,
267 we will add then when we need them basically.
271 =item B<associated_metaclass>
273 This returns the metaclass associated with this instance.
275 =item B<get_all_slots>
277 This will return the current list of slots based on what was
278 given to this object in C<new>.
280 =item B<is_valid_slot ($slot_name)>
282 This will return true if C<$slot_name> is a valid slot name.
284 =item B<is_dependent_on_superclasses>
286 This method returns true when the meta instance must be recreated on any
293 =head2 Operations on Instance Structures
295 An important distinction of this sub-protocol is that the
296 instance meta-object is a different entity from the actual
297 instance it creates. For this reason, any actions on slots
298 require that the C<$instance_structure> is passed into them.
300 The names of these methods pretty much explain exactly
301 what they do, if that is not enough then I suggest reading
302 the source, it is very straightfoward.
306 =item B<get_slot_value ($instance_structure, $slot_name)>
308 =item B<set_slot_value ($instance_structure, $slot_name, $value)>
310 =item B<initialize_slot ($instance_structure, $slot_name)>
312 =item B<deinitialize_slot ($instance_structure, $slot_name)>
314 =item B<initialize_all_slots ($instance_structure)>
316 =item B<deinitialize_all_slots ($instance_structure)>
318 =item B<is_slot_initialized ($instance_structure, $slot_name)>
320 =item B<weaken_slot_value ($instance_structure, $slot_name)>
322 =item B<strengthen_slot_value ($instance_structure, $slot_name)>
324 =item B<rebless_instance_structure ($instance_structure, $new_metaclass)>
328 =head2 Inlineable Instance Operations
332 =item B<is_inlinable>
334 Each meta-instance should override this method to tell Class::MOP if it's
335 possible to inline the slot access. This is currently only used by
336 L<Class::MOP::Immutable> when performing optimizations.
338 =item B<inline_create_instance>
340 =item B<inline_slot_access ($instance_structure, $slot_name)>
342 =item B<inline_get_slot_value ($instance_structure, $slot_name)>
344 =item B<inline_set_slot_value ($instance_structure, $slot_name, $value)>
346 =item B<inline_initialize_slot ($instance_structure, $slot_name)>
348 =item B<inline_deinitialize_slot ($instance_structure, $slot_name)>
350 =item B<inline_is_slot_initialized ($instance_structure, $slot_name)>
352 =item B<inline_weaken_slot_value ($instance_structure, $slot_name)>
354 =item B<inline_strengthen_slot_value ($instance_structure, $slot_name)>
360 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
362 Stevan Little E<lt>stevan@iinteractive.comE<gt>
364 =head1 COPYRIGHT AND LICENSE
366 Copyright 2006-2008 by Infinity Interactive, Inc.
368 L<http://www.iinteractive.com>
370 This library is free software; you can redistribute it and/or modify
371 it under the same terms as Perl itself.