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, "metaclass";
19 } elsif ( @args >= 2 && blessed($args[0]) && $args[0]->isa("Class::MOP::Class") ) {
21 my ( $meta, @attrs ) = @args;
22 @args = ( metaclass => $meta, attributes => \@attrs );
28 $options{slots} ||= [ map { $_->slots } @{ $options{attributes} || [] } ];
30 # FIXME replace with a proper constructor
31 my $instance = bless {
33 # I am not sure that it makes
34 # sense to pass in the meta
35 # The ideal would be to just
36 # pass in the class name, but
37 # that is placing too much of
38 # an assumption on bless(),
39 # which is *probably* a safe
40 # assumption,.. but you can
42 'meta' => $options{metaclass}, # FIXME rename to associated metaclass with a compat alias?
43 'slots' => { map { $_ => undef } @{ $options{slots} } },
46 # FIXME weak_ref => 1,
47 weaken($instance->{'meta'});
52 sub associated_metaclass { (shift)->{'meta'} }
56 $self->bless_instance_structure({});
59 sub bless_instance_structure {
60 my ($self, $instance_structure) = @_;
61 bless $instance_structure, $self->associated_metaclass->name;
65 my ($self, $instance) = @_;
66 $self->bless_instance_structure({ %$instance });
69 # operations on meta instance
73 return keys %{$self->{'slots'}};
77 my ($self, $slot_name) = @_;
78 exists $self->{'slots'}->{$slot_name};
81 # operations on created instances
84 my ($self, $instance, $slot_name) = @_;
85 $instance->{$slot_name};
89 my ($self, $instance, $slot_name, $value) = @_;
90 $instance->{$slot_name} = $value;
94 my ($self, $instance, $slot_name) = @_;
98 sub deinitialize_slot {
99 my ( $self, $instance, $slot_name ) = @_;
100 delete $instance->{$slot_name};
103 sub initialize_all_slots {
104 my ($self, $instance) = @_;
105 foreach my $slot_name ($self->get_all_slots) {
106 $self->initialize_slot($instance, $slot_name);
110 sub deinitialize_all_slots {
111 my ($self, $instance) = @_;
112 foreach my $slot_name ($self->get_all_slots) {
113 $self->deinitialize_slot($instance, $slot_name);
117 sub is_slot_initialized {
118 my ($self, $instance, $slot_name, $value) = @_;
119 exists $instance->{$slot_name};
122 sub weaken_slot_value {
123 my ($self, $instance, $slot_name) = @_;
124 weaken $instance->{$slot_name};
127 sub strengthen_slot_value {
128 my ($self, $instance, $slot_name) = @_;
129 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
132 sub rebless_instance_structure {
133 my ($self, $instance, $metaclass) = @_;
134 bless $instance, $metaclass->name;
137 # inlinable operation snippets
139 sub is_inlinable { 1 }
141 sub inline_create_instance {
142 my ($self, $class_variable) = @_;
143 'bless {} => ' . $class_variable;
146 sub inline_slot_access {
147 my ($self, $instance, $slot_name) = @_;
148 sprintf "%s->{%s}", $instance, $slot_name;
151 sub inline_get_slot_value {
152 my ($self, $instance, $slot_name) = @_;
153 $self->inline_slot_access($instance, $slot_name);
156 sub inline_set_slot_value {
157 my ($self, $instance, $slot_name, $value) = @_;
158 $self->inline_slot_access($instance, $slot_name) . " = $value",
161 sub inline_initialize_slot {
162 my ($self, $instance, $slot_name) = @_;
166 sub inline_deinitialize_slot {
167 my ($self, $instance, $slot_name) = @_;
168 "delete " . $self->inline_slot_access($instance, $slot_name);
170 sub inline_is_slot_initialized {
171 my ($self, $instance, $slot_name) = @_;
172 "exists " . $self->inline_slot_access($instance, $slot_name);
175 sub inline_weaken_slot_value {
176 my ($self, $instance, $slot_name) = @_;
177 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
180 sub inline_strengthen_slot_value {
181 my ($self, $instance, $slot_name) = @_;
182 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
193 Class::MOP::Instance - Instance Meta Object
197 The meta instance is used by attributes for low level storage.
199 Using this API generally violates attribute encapsulation and is not
200 recommended, instead look at L<Class::MOP::Attribute/get_value>,
201 L<Class::MOP::Attribute/set_value> for the recommended way to fiddle with
202 attribute values in a generic way, independent of how/whether accessors have
203 been defined. Accessors can be found using L<Class::MOP::Class/get_attribute>.
205 This may seem like over-abstraction, but by abstracting
206 this process into a sub-protocol we make it possible to
207 easily switch the details of how an object's instance is
208 stored with minimal impact. In most cases just subclassing
209 this class will be all you need to do (see the examples;
210 F<examples/ArrayBasedStorage.pod> and
211 F<examples/InsideOutClass.pod> for details).
217 =item B<new ($meta, @attrs)>
219 Creates a new instance meta-object and gathers all the slots from
220 the list of C<@attrs> given.
224 This will return a B<Class::MOP::Class> instance which is related
229 =head2 Creation of Instances
233 =item B<create_instance>
235 This creates the appropriate structure needed for the instance and
236 then calls C<bless_instance_structure> to bless it into the class.
238 =item B<bless_instance_structure ($instance_structure)>
240 This does just exactly what it says it does.
242 =item B<clone_instance ($instance_structure)>
244 This too does just exactly what it says it does.
250 NOTE: There might be more methods added to this part of the API,
251 we will add then when we need them basically.
255 =item B<associated_metaclass>
257 This returns the metaclass associated with this instance.
259 =item B<get_all_slots>
261 This will return the current list of slots based on what was
262 given to this object in C<new>.
264 =item B<is_valid_slot ($slot_name)>
266 This will return true if C<$slot_name> is a valid slot name.
270 =head2 Operations on Instance Structures
272 An important distinction of this sub-protocol is that the
273 instance meta-object is a different entity from the actual
274 instance it creates. For this reason, any actions on slots
275 require that the C<$instance_structure> is passed into them.
277 The names of these methods pretty much explain exactly
278 what they do, if that is not enough then I suggest reading
279 the source, it is very straightfoward.
283 =item B<get_slot_value ($instance_structure, $slot_name)>
285 =item B<set_slot_value ($instance_structure, $slot_name, $value)>
287 =item B<initialize_slot ($instance_structure, $slot_name)>
289 =item B<deinitialize_slot ($instance_structure, $slot_name)>
291 =item B<initialize_all_slots ($instance_structure)>
293 =item B<deinitialize_all_slots ($instance_structure)>
295 =item B<is_slot_initialized ($instance_structure, $slot_name)>
297 =item B<weaken_slot_value ($instance_structure, $slot_name)>
299 =item B<strengthen_slot_value ($instance_structure, $slot_name)>
301 =item B<rebless_instance_structure ($instance_structure, $new_metaclass)>
305 =head2 Inlineable Instance Operations
309 =item B<is_inlinable>
311 Each meta-instance should override this method to tell Class::MOP if it's
312 possible to inline the slot access. This is currently only used by
313 L<Class::MOP::Immutable> when performing optimizations.
315 =item B<inline_create_instance>
317 =item B<inline_slot_access ($instance_structure, $slot_name)>
319 =item B<inline_get_slot_value ($instance_structure, $slot_name)>
321 =item B<inline_set_slot_value ($instance_structure, $slot_name, $value)>
323 =item B<inline_initialize_slot ($instance_structure, $slot_name)>
325 =item B<inline_deinitialize_slot ($instance_structure, $slot_name)>
327 =item B<inline_is_slot_initialized ($instance_structure, $slot_name)>
329 =item B<inline_weaken_slot_value ($instance_structure, $slot_name)>
331 =item B<inline_strengthen_slot_value ($instance_structure, $slot_name)>
337 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
339 Stevan Little E<lt>stevan@iinteractive.comE<gt>
341 =head1 COPYRIGHT AND LICENSE
343 Copyright 2006-2008 by Infinity Interactive, Inc.
345 L<http://www.iinteractive.com>
347 This library is free software; you can redistribute it and/or modify
348 it under the same terms as Perl itself.