2 package Class::MOP::Instance;
7 use Scalar::Util 'weaken', 'blessed';
12 require Class::MOP::Class;
13 Class::MOP::Class->initialize(blessed($_[0]) || $_[0]);
17 my ($class, $meta, @attrs) = @_;
18 my @slots = map { $_->slots } @attrs;
21 # I am not sure that it makes
22 # sense to pass in the meta
23 # The ideal would be to just
24 # pass in the class name, but
25 # that is placing too much of
26 # an assumption on bless(),
27 # which is *probably* a safe
28 # assumption,.. but you can
31 slots => { map { $_ => undef } @slots },
37 $self->bless_instance_structure({});
40 sub bless_instance_structure {
41 my ($self, $instance_structure) = @_;
42 bless $instance_structure, $self->{meta}->name;
46 my ($self, $instance) = @_;
47 $self->bless_instance_structure({ %$instance });
50 # operations on meta instance
54 return keys %{$self->{slots}};
58 my ($self, $slot_name) = @_;
59 exists $self->{slots}->{$slot_name} ? 1 : 0;
62 # operations on created instances
65 my ($self, $instance, $slot_name) = @_;
66 return $instance->{$slot_name};
70 my ($self, $instance, $slot_name, $value) = @_;
71 $instance->{$slot_name} = $value;
75 my ($self, $instance, $slot_name) = @_;
76 $self->set_slot_value($instance, $slot_name, undef);
79 sub deinitialize_slot {
80 my ( $self, $instance, $slot_name ) = @_;
81 delete $instance->{$slot_name};
84 sub initialize_all_slots {
85 my ($self, $instance) = @_;
86 foreach my $slot_name ($self->get_all_slots) {
87 $self->initialize_slot($instance, $slot_name);
91 sub deinitialize_all_slots {
92 my ($self, $instance) = @_;
93 foreach my $slot_name ($self->get_all_slots) {
94 $self->deinitialize_slot($instance, $slot_name);
98 sub is_slot_initialized {
99 my ($self, $instance, $slot_name, $value) = @_;
100 exists $instance->{$slot_name} ? 1 : 0;
103 sub weaken_slot_value {
104 my ($self, $instance, $slot_name) = @_;
105 weaken $instance->{$slot_name};
108 sub strengthen_slot_value {
109 my ($self, $instance, $slot_name) = @_;
110 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
113 # inlinable operation snippets
115 sub is_inlinable { 1 }
117 sub inline_create_instance {
118 my ($self, $class_variable) = @_;
119 'bless {} => ' . $class_variable;
122 sub inline_slot_access {
123 my ($self, $instance, $slot_name) = @_;
124 sprintf "%s->{%s}", $instance, $slot_name;
127 sub inline_get_slot_value {
128 my ($self, $instance, $slot_name) = @_;
129 $self->inline_slot_access($instance, $slot_name);
132 sub inline_set_slot_value {
133 my ($self, $instance, $slot_name, $value) = @_;
134 $self->inline_slot_access($instance, $slot_name) . " = $value",
137 sub inline_initialize_slot {
138 my ($self, $instance, $slot_name) = @_;
139 $self->inline_set_slot_value($instance, $slot_name, 'undef'),
142 sub inline_deinitialize_slot {
143 my ($self, $instance, $slot_name) = @_;
144 "delete " . $self->inline_slot_access($instance, $slot_name);
146 sub inline_is_slot_initialized {
147 my ($self, $instance, $slot_name) = @_;
148 "exists " . $self->inline_slot_access($instance, $slot_name) . " ? 1 : 0";
151 sub inline_weaken_slot_value {
152 my ($self, $instance, $slot_name) = @_;
153 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
156 sub inline_strengthen_slot_value {
157 my ($self, $instance, $slot_name) = @_;
158 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
169 Class::MOP::Instance - Instance Meta Object
173 # for the most part, this protocol is internal
174 # and not for public usage, but this how one
182 ':instance_metaclass' => 'ArrayBasedStorage::Instance',
185 # now Foo->new produces blessed ARRAY ref based objects
189 This is a sub-protocol which governs instance creation
190 and access to the slots of the instance structure.
192 This may seem like over-abstraction, but by abstracting
193 this process into a sub-protocol we make it possible to
194 easily switch the details of how an object's instance is
195 stored with minimal impact. In most cases just subclassing
196 this class will be all you need to do (see the examples;
197 F<examples/ArrayBasedStorage.pod> and
198 F<examples/InsideOutClass.pod> for details).
204 =item B<new ($meta, @attrs)>
206 Creates a new instance meta-object and gathers all the slots from
207 the list of C<@attrs> given.
211 This will return a B<Class::MOP::Class> instance which is related
216 =head2 Creation of Instances
220 =item B<create_instance>
222 This creates the appropriate structure needed for the instance and
223 then calls C<bless_instance_structure> to bless it into the class.
225 =item B<bless_instance_structure ($instance_structure)>
227 This does just exactly what it says it does.
229 =item B<clone_instance ($instance_structure)>
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<get_all_slots>
242 This will return the current list of slots based on what was
243 given to this object in C<new>.
245 =item B<is_valid_slot ($slot_name)>
249 =head2 Operations on Instance Structures
251 An important distinction of this sub-protocol is that the
252 instance meta-object is a different entity from the actual
253 instance it creates. For this reason, any actions on slots
254 require that the C<$instance_structure> is passed into them.
258 =item B<get_slot_value ($instance_structure, $slot_name)>
260 =item B<set_slot_value ($instance_structure, $slot_name, $value)>
262 =item B<initialize_slot ($instance_structure, $slot_name)>
264 =item B<deinitialize_slot ($instance_structure, $slot_name)>
266 =item B<initialize_all_slots ($instance_structure)>
268 =item B<deinitialize_all_slots ($instance_structure)>
270 =item B<is_slot_initialized ($instance_structure, $slot_name)>
272 =item B<weaken_slot_value ($instance_structure, $slot_name)>
274 =item B<strengthen_slot_value ($instance_structure, $slot_name)>
278 =head2 Inlineable Instance Operations
280 This part of the API is currently un-used. It is there for use
281 in future experiments in class finailization mostly. Best to
286 =item B<is_inlinable>
288 Each meta-instance should override this method to tell Class::MOP if it's
289 possible to inline the slot access.
291 This is currently only used by Class::MOP::Class::Immutable when performing
294 =item B<inline_create_instance>
296 =item B<inline_slot_access ($instance_structure, $slot_name)>
298 =item B<inline_get_slot_value ($instance_structure, $slot_name)>
300 =item B<inline_set_slot_value ($instance_structure, $slot_name, $value)>
302 =item B<inline_initialize_slot ($instance_structure, $slot_name)>
304 =item B<inline_deinitialize_slot ($instance_structure, $slot_name)>
306 =item B<inline_is_slot_initialized ($instance_structure, $slot_name)>
308 =item B<inline_weaken_slot_value ($instance_structure, $slot_name)>
310 =item B<inline_strengthen_slot_value ($instance_structure, $slot_name)>
316 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
318 Stevan Little E<lt>stevan@iinteractive.comE<gt>
320 =head1 COPYRIGHT AND LICENSE
322 Copyright 2006 by Infinity Interactive, Inc.
324 L<http://www.iinteractive.com>
326 This library is free software; you can redistribute it and/or modify
327 it under the same terms as Perl itself.