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, $meta, @attrs) = @_;
16 my @slots = map { $_->slots } @attrs;
17 my $instance = bless {
19 # I am not sure that it makes
20 # sense to pass in the meta
21 # The ideal would be to just
22 # pass in the class name, but
23 # that is placing too much of
24 # an assumption on bless(),
25 # which is *probably* a safe
26 # assumption,.. but you can
29 '@!slots' => { map { $_ => undef } @slots },
32 weaken($instance->{'$!meta'});
37 sub associated_metaclass { (shift)->{'$!meta'} }
41 $self->bless_instance_structure({});
44 sub bless_instance_structure {
45 my ($self, $instance_structure) = @_;
46 bless $instance_structure, $self->associated_metaclass->name;
50 my ($self, $instance) = @_;
51 $self->bless_instance_structure({ %$instance });
54 # operations on meta instance
58 return keys %{$self->{'@!slots'}};
62 my ($self, $slot_name) = @_;
63 exists $self->{'@!slots'}->{$slot_name};
66 # operations on created instances
69 my ($self, $instance, $slot_name) = @_;
70 $instance->{$slot_name};
74 my ($self, $instance, $slot_name, $value) = @_;
75 $instance->{$slot_name} = $value;
79 my ($self, $instance, $slot_name) = @_;
80 #$self->set_slot_value($instance, $slot_name, undef);
83 sub deinitialize_slot {
84 my ( $self, $instance, $slot_name ) = @_;
85 delete $instance->{$slot_name};
88 sub initialize_all_slots {
89 my ($self, $instance) = @_;
90 foreach my $slot_name ($self->get_all_slots) {
91 $self->initialize_slot($instance, $slot_name);
95 sub deinitialize_all_slots {
96 my ($self, $instance) = @_;
97 foreach my $slot_name ($self->get_all_slots) {
98 $self->deinitialize_slot($instance, $slot_name);
102 sub is_slot_initialized {
103 my ($self, $instance, $slot_name, $value) = @_;
104 exists $instance->{$slot_name};
107 sub weaken_slot_value {
108 my ($self, $instance, $slot_name) = @_;
109 weaken $instance->{$slot_name};
112 sub strengthen_slot_value {
113 my ($self, $instance, $slot_name) = @_;
114 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
117 sub rebless_instance_structure {
118 my ($self, $instance, $metaclass) = @_;
119 bless $instance, $metaclass->name;
122 # inlinable operation snippets
124 sub is_inlinable { 1 }
126 sub inline_create_instance {
127 my ($self, $class_variable) = @_;
128 'bless {} => ' . $class_variable;
131 sub inline_slot_access {
132 my ($self, $instance, $slot_name) = @_;
133 sprintf "%s->{%s}", $instance, $slot_name;
136 sub inline_get_slot_value {
137 my ($self, $instance, $slot_name) = @_;
138 $self->inline_slot_access($instance, $slot_name);
141 sub inline_set_slot_value {
142 my ($self, $instance, $slot_name, $value) = @_;
143 $self->inline_slot_access($instance, $slot_name) . " = $value",
146 sub inline_initialize_slot {
147 my ($self, $instance, $slot_name) = @_;
148 $self->inline_set_slot_value($instance, $slot_name, 'undef'),
151 sub inline_deinitialize_slot {
152 my ($self, $instance, $slot_name) = @_;
153 "delete " . $self->inline_slot_access($instance, $slot_name);
155 sub inline_is_slot_initialized {
156 my ($self, $instance, $slot_name) = @_;
157 "exists " . $self->inline_slot_access($instance, $slot_name);
160 sub inline_weaken_slot_value {
161 my ($self, $instance, $slot_name) = @_;
162 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
165 sub inline_strengthen_slot_value {
166 my ($self, $instance, $slot_name) = @_;
167 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
178 Class::MOP::Instance - Instance Meta Object
182 The meta instance is used by attributes for low level storage.
184 Using this API generally violates attribute encapsulation and is not
185 reccomended, instead look at L<Class::MOP::Attribute/get_value>,
186 L<Class::MOP::Attribute/set_value> for the reccomended way to fiddle with
187 attribute values in a generic way, independant of how/whether accessors have
188 been defined. Accessors can be found using L<Class::MOP::Class/get_attribute>.
190 This may seem like over-abstraction, but by abstracting
191 this process into a sub-protocol we make it possible to
192 easily switch the details of how an object's instance is
193 stored with minimal impact. In most cases just subclassing
194 this class will be all you need to do (see the examples;
195 F<examples/ArrayBasedStorage.pod> and
196 F<examples/InsideOutClass.pod> for details).
202 =item B<new ($meta, @attrs)>
204 Creates a new instance meta-object and gathers all the slots from
205 the list of C<@attrs> given.
209 This will return a B<Class::MOP::Class> instance which is related
214 =head2 Creation of Instances
218 =item B<create_instance>
220 This creates the appropriate structure needed for the instance and
221 then calls C<bless_instance_structure> to bless it into the class.
223 =item B<bless_instance_structure ($instance_structure)>
225 This does just exactly what it says it does.
227 =item B<clone_instance ($instance_structure)>
229 This too does just exactly what it says it does.
233 =head2 Instrospection
235 NOTE: There might be more methods added to this part of the API,
236 we will add then when we need them basically.
240 =item B<associated_metaclass>
242 This returns the metaclass associated with this instance.
244 =item B<get_all_slots>
246 This will return the current list of slots based on what was
247 given to this object in C<new>.
249 =item B<is_valid_slot ($slot_name)>
251 This will return true if C<$slot_name> is a valid slot name.
255 =head2 Operations on Instance Structures
257 An important distinction of this sub-protocol is that the
258 instance meta-object is a different entity from the actual
259 instance it creates. For this reason, any actions on slots
260 require that the C<$instance_structure> is passed into them.
262 The names of these methods pretty much explain exactly
263 what they do, if that is not enough then I suggest reading
264 the source, it is very straightfoward.
268 =item B<get_slot_value ($instance_structure, $slot_name)>
270 =item B<set_slot_value ($instance_structure, $slot_name, $value)>
272 =item B<initialize_slot ($instance_structure, $slot_name)>
274 =item B<deinitialize_slot ($instance_structure, $slot_name)>
276 =item B<initialize_all_slots ($instance_structure)>
278 =item B<deinitialize_all_slots ($instance_structure)>
280 =item B<is_slot_initialized ($instance_structure, $slot_name)>
282 =item B<weaken_slot_value ($instance_structure, $slot_name)>
284 =item B<strengthen_slot_value ($instance_structure, $slot_name)>
286 =item B<rebless_instance_structure ($instance_structure, $new_metaclass)>
290 =head2 Inlineable Instance Operations
294 =item B<is_inlinable>
296 Each meta-instance should override this method to tell Class::MOP if it's
297 possible to inline the slot access. This is currently only used by
298 L<Class::MOP::Immutable> when performing optimizations.
300 =item B<inline_create_instance>
302 =item B<inline_slot_access ($instance_structure, $slot_name)>
304 =item B<inline_get_slot_value ($instance_structure, $slot_name)>
306 =item B<inline_set_slot_value ($instance_structure, $slot_name, $value)>
308 =item B<inline_initialize_slot ($instance_structure, $slot_name)>
310 =item B<inline_deinitialize_slot ($instance_structure, $slot_name)>
312 =item B<inline_is_slot_initialized ($instance_structure, $slot_name)>
314 =item B<inline_weaken_slot_value ($instance_structure, $slot_name)>
316 =item B<inline_strengthen_slot_value ($instance_structure, $slot_name)>
322 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
324 Stevan Little E<lt>stevan@iinteractive.comE<gt>
326 =head1 COPYRIGHT AND LICENSE
328 Copyright 2006-2008 by Infinity Interactive, Inc.
330 L<http://www.iinteractive.com>
332 This library is free software; you can redistribute it and/or modify
333 it under the same terms as Perl itself.