use X Protocol phrase in docs for each module
[gitmo/Class-MOP.git] / lib / Class / MOP / Instance.pm
CommitLineData
24869f62 1
2package Class::MOP::Instance;
3
4use strict;
5use warnings;
6
fa16e528 7use Scalar::Util 'weaken', 'blessed';
24869f62 8
eca95e04 9our $VERSION = '0.78';
d519662a 10$VERSION = eval $VERSION;
f0480c45 11our $AUTHORITY = 'cpan:STEVAN';
24869f62 12
d7b2249e 13use base 'Class::MOP::Object';
24869f62 14
63d08a9e 15sub BUILDARGS {
d43737b3 16 my ($class, @args) = @_;
17
18 if ( @args == 1 ) {
63d08a9e 19 unshift @args, "associated_metaclass";
d43737b3 20 } elsif ( @args >= 2 && blessed($args[0]) && $args[0]->isa("Class::MOP::Class") ) {
21 # compat mode
22 my ( $meta, @attrs ) = @args;
63d08a9e 23 @args = ( associated_metaclass => $meta, attributes => \@attrs );
d43737b3 24 }
25
26 my %options = @args;
7c7fd869 27 # FIXME lazy_build
d43737b3 28 $options{slots} ||= [ map { $_->slots } @{ $options{attributes} || [] } ];
63d08a9e 29 $options{slot_hash} = { map { $_ => undef } @{ $options{slots} } }; # FIXME lazy_build
30
31 return \%options;
32}
33
34sub new {
35 my $class = shift;
36 my $options = $class->BUILDARGS(@_);
d43737b3 37
38 # FIXME replace with a proper constructor
b4b5d65a 39 my $instance = $class->_new(%$options);
40
41 # FIXME weak_ref => 1,
42 weaken($instance->{'associated_metaclass'});
43
44 return $instance;
45}
46
47sub _new {
48 my ( $class, %options ) = @_;
49 bless {
fc3ddd1d 50 # NOTE:
51 # I am not sure that it makes
52 # sense to pass in the meta
8d2d4c67 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(),
fc3ddd1d 57 # which is *probably* a safe
8d2d4c67 58 # assumption,.. but you can
fc3ddd1d 59 # never tell <:)
b4b5d65a 60 'associated_metaclass' => $options{associated_metaclass},
61 'attributes' => $options{attributes},
62 'slots' => $options{slots},
63 'slot_hash' => $options{slot_hash},
8d2d4c67 64 } => $class;
24869f62 65}
66
74890687 67sub _class_name { $_[0]->{_class_name} ||= $_[0]->associated_metaclass->name }
68
69sub associated_metaclass { $_[0]{'associated_metaclass'} }
c23184fc 70
49c93440 71sub create_instance {
72 my $self = shift;
becd03c6 73 bless {}, $self->_class_name;
2d711cc8 74}
75
becd03c6 76# for compatibility
49c93440 77sub bless_instance_structure {
78 my ($self, $instance_structure) = @_;
74890687 79 bless $instance_structure, $self->_class_name;
2d711cc8 80}
81
f7259199 82sub clone_instance {
83 my ($self, $instance) = @_;
becd03c6 84 bless { %$instance }, $self->_class_name;
f7259199 85}
86
2d711cc8 87# operations on meta instance
88
eb49acde 89sub get_all_slots {
90 my $self = shift;
7c7fd869 91 return @{$self->{'slots'}};
f7259199 92}
93
0b5d46da 94sub get_all_attributes {
95 my $self = shift;
96 return @{$self->{attributes}};
97}
98
f7259199 99sub is_valid_slot {
100 my ($self, $slot_name) = @_;
7c7fd869 101 exists $self->{'slot_hash'}->{$slot_name};
839ea973 102}
103
2d711cc8 104# operations on created instances
105
839ea973 106sub get_slot_value {
2bab2be6 107 my ($self, $instance, $slot_name) = @_;
230472a7 108 $instance->{$slot_name};
839ea973 109}
110
2bab2be6 111sub set_slot_value {
112 my ($self, $instance, $slot_name, $value) = @_;
113 $instance->{$slot_name} = $value;
114}
115
2d711cc8 116sub initialize_slot {
49c93440 117 my ($self, $instance, $slot_name) = @_;
a007159d 118 return;
2d711cc8 119}
120
7d28758b 121sub deinitialize_slot {
122 my ( $self, $instance, $slot_name ) = @_;
123 delete $instance->{$slot_name};
124}
125
c174112e 126sub initialize_all_slots {
127 my ($self, $instance) = @_;
128 foreach my $slot_name ($self->get_all_slots) {
129 $self->initialize_slot($instance, $slot_name);
130 }
131}
132
7d28758b 133sub deinitialize_all_slots {
134 my ($self, $instance) = @_;
135 foreach my $slot_name ($self->get_all_slots) {
136 $self->deinitialize_slot($instance, $slot_name);
137 }
138}
139
49c93440 140sub is_slot_initialized {
141 my ($self, $instance, $slot_name, $value) = @_;
230472a7 142 exists $instance->{$slot_name};
2bab2be6 143}
839ea973 144
5582521c 145sub weaken_slot_value {
69e3ab0a 146 my ($self, $instance, $slot_name) = @_;
147 weaken $instance->{$slot_name};
5582521c 148}
149
150sub strengthen_slot_value {
69e3ab0a 151 my ($self, $instance, $slot_name) = @_;
152 $self->set_slot_value($instance, $slot_name, $self->get_slot_value($instance, $slot_name));
5582521c 153}
154
3d9e4646 155sub rebless_instance_structure {
156 my ($self, $instance, $metaclass) = @_;
feb93c85 157
158 # we use $_[1] here because of t/306_rebless_overload.t regressions on 5.8.8
159 bless $_[1], $metaclass->name;
3d9e4646 160}
161
da5680be 162sub is_dependent_on_superclasses {
163 return; # for meta instances that require updates on inherited slot changes
164}
165
ee7c0467 166# inlinable operation snippets
167
c0cbf4d9 168sub is_inlinable { 1 }
169
170sub inline_create_instance {
171 my ($self, $class_variable) = @_;
172 'bless {} => ' . $class_variable;
173}
174
ee7c0467 175sub inline_slot_access {
176 my ($self, $instance, $slot_name) = @_;
e9a19694 177 sprintf q[%s->{"%s"}], $instance, quotemeta($slot_name);
ee7c0467 178}
179
180sub inline_get_slot_value {
181 my ($self, $instance, $slot_name) = @_;
230472a7 182 $self->inline_slot_access($instance, $slot_name);
ee7c0467 183}
184
185sub inline_set_slot_value {
186 my ($self, $instance, $slot_name, $value) = @_;
8d2d4c67 187 $self->inline_slot_access($instance, $slot_name) . " = $value",
ee7c0467 188}
189
190sub inline_initialize_slot {
191 my ($self, $instance, $slot_name) = @_;
a007159d 192 return '';
ee7c0467 193}
194
7d28758b 195sub inline_deinitialize_slot {
196 my ($self, $instance, $slot_name) = @_;
197 "delete " . $self->inline_slot_access($instance, $slot_name);
198}
ee7c0467 199sub inline_is_slot_initialized {
200 my ($self, $instance, $slot_name) = @_;
230472a7 201 "exists " . $self->inline_slot_access($instance, $slot_name);
ee7c0467 202}
203
204sub inline_weaken_slot_value {
205 my ($self, $instance, $slot_name) = @_;
206 sprintf "Scalar::Util::weaken( %s )", $self->inline_slot_access($instance, $slot_name);
207}
208
209sub inline_strengthen_slot_value {
210 my ($self, $instance, $slot_name) = @_;
211 $self->inline_set_slot_value($instance, $slot_name, $self->inline_slot_access($instance, $slot_name));
212}
213
24869f62 2141;
215
216__END__
217
218=pod
219
8d2d4c67 220=head1 NAME
24869f62 221
222Class::MOP::Instance - Instance Meta Object
223
24869f62 224=head1 DESCRIPTION
225
ba1b8aa2 226The Instance Protocol controls the creation of object instances, and
20315887 227the storage of attribute values in those instances.
228
229Using this API directly in your own code violates encapsulation, and
230we recommend that you use the appropriate APIs in L<Class::MOP::Class>
231and L<Class::MOP::Attribute> instead. Those APIs in turn call the
232methods in this class as appropriate.
233
234This class also participates in generating inlined code by providing
235snippets of code to access an object instance.
9fa4d0b4 236
24869f62 237=head1 METHODS
238
20315887 239=head2 Object construction
240
24869f62 241=over 4
242
20315887 243=item B<< Class::MOP::Instance->new(%options) >>
9fa4d0b4 244
20315887 245This method creates a new meta-instance object.
9fa4d0b4 246
20315887 247It accepts the following keys in C<%options>:
63d08a9e 248
20315887 249=over 8
63d08a9e 250
20315887 251=item * associated_metaclass
9fa4d0b4 252
20315887 253The L<Class::MOP::Class> object for which instances will be created.
9fa4d0b4 254
20315887 255=item * attributes
9fa4d0b4 256
20315887 257An array reference of L<Class::MOP::Attribute> objects. These are the
258attributes which can be stored in each instance.
9fa4d0b4 259
20315887 260=back
24869f62 261
20315887 262=back
58287a97 263
20315887 264=head2 Creating and altering instances
0e76a376 265
20315887 266=over 4
839ea973 267
20315887 268=item B<< $metainstance->create_instance >>
0e76a376 269
20315887 270This method returns a reference blessed into the associated
271metaclass's class.
becd03c6 272
20315887 273The default is to use a hash reference. Subclasses can override this.
f7259199 274
20315887 275=item B<< $metainstance->clone_instance($instance) >>
276
277Given an instance, this method creates a new object by making
278I<shallow> clone of the original.
127d39a7 279
9fa4d0b4 280=back
839ea973 281
98bf345b 282=head2 Introspection
58287a97 283
9fa4d0b4 284=over 4
285
20315887 286=item B<< $metainstance->associated_metaclass >>
c23184fc 287
20315887 288This returns the L<Class::MOP::Class> object associated with the
289meta-instance object.
127d39a7 290
20315887 291=item B<< $metainstance->get_all_slots >>
9fa4d0b4 292
20315887 293This returns a list of slot names stored in object instances. In
294almost all cases, slot names correspond directly attribute names.
58287a97 295
20315887 296=item B<< $metainstance->is_valid_slot($slot_name) >>
f7259199 297
127d39a7 298This will return true if C<$slot_name> is a valid slot name.
299
20315887 300=item B<< $metainstance->get_all_attributes >>
da5680be 301
20315887 302This returns a list of attributes corresponding to the attributes
303passed to the constructor.
0202ee96 304
24869f62 305=back
306
9fa4d0b4 307=head2 Operations on Instance Structures
308
20315887 309It's important to understand that the meta-instance object is a
310different entity from the actual instances it creates. For this
311reason, any operations on the C<$instance_structure> always require
312that the object instance be passed to the method.
127d39a7 313
24869f62 314=over 4
315
20315887 316=item B<< $metainstance->get_slot_value($instance_structure, $slot_name) >>
317
318=item B<< $metainstance->set_slot_value($instance_structure, $slot_name, $value) >>
24869f62 319
20315887 320=item B<< $metainstance->initialize_slot($instance_structure, $slot_name) >>
9fa4d0b4 321
20315887 322=item B<< $metainstance->deinitialize_slot($instance_structure, $slot_name) >>
9fa4d0b4 323
20315887 324=item B<< $metainstance->initialize_all_slots($instance_structure) >>
7d28758b 325
20315887 326=item B<< $metainstance->deinitialize_all_slots($instance_structure) >>
9fa4d0b4 327
20315887 328=item B<< $metainstance->is_slot_initialized($instance_structure, $slot_name) >>
7d28758b 329
20315887 330=item B<< $metainstance->weaken_slot_value($instance_structure, $slot_name) >>
24869f62 331
20315887 332=item B<< $metainstance->strengthen_slot_value($instance_structure, $slot_name) >>
ee7c0467 333
20315887 334=item B<< $metainstance->rebless_instance_structure($instance_structure, $new_metaclass) >>
ee7c0467 335
20315887 336The exact details of what each method does should be fairly obvious
337from the method name.
5fdf066d 338
ee7c0467 339=back
340
20315887 341=head2 Inlinable Instance Operations
ee7c0467 342
343=over 4
344
20315887 345=item B<< $metainstance->is_inlinable >>
c0cbf4d9 346
20315887 347This is a boolean that indicates whether or not slot access operations
348can be inlined. By default it is true, but subclasses can override
349this.
c0cbf4d9 350
20315887 351=item B<< $metainstance->inline_create_instance($class_variable) >>
495af518 352
20315887 353This method expects a string that, I<when inlined>, will become a
354class name. This would literally be something like C<'$class'>, not an
355actual class name.
ee7c0467 356
20315887 357It returns a snippet of code that creates a new object for the
358class. This is something like C< bless {}, $class_name >.
ee7c0467 359
20315887 360=item B<< $metainstance->inline_slot_access($instance_variable, $slot_name) >>
ee7c0467 361
20315887 362=item B<< $metainstance->inline_get_slot_value($instance_variable, $slot_name) >>
ee7c0467 363
20315887 364=item B<< $metainstance->inline_set_slot_value($instance_variable, $slot_name, $value) >>
365
366=item B<< $metainstance->inline_initialize_slot($instance_variable, $slot_name) >>
367
368=item B<< $metainstance->inline_deinitialize_slot($instance_variable, $slot_name) >>
369
370=item B<< $metainstance->inline_is_slot_initialized($instance_variable, $slot_name) >>
371
372=item B<< $metainstance->inline_weaken_slot_value($instance_variable, $slot_name) >>
373
374=item B<< $metainstance->inline_strengthen_slot_value($instance_variable, $slot_name) >>
375
376These methods all expect two arguments. The first is the name of a
377variable, than when inlined, will represent the object
378instance. Typically this will be a literal string like C<'$_[0]'>.
379
380The second argument is a slot name.
381
382The method returns a snippet of code that, when inlined, performs some
383operation on the instance.
384
385=back
386
387=head2 Introspection
388
389=over 4
7d28758b 390
20315887 391=item B<< Class::MOP::Instance->meta >>
5582521c 392
20315887 393This will return a L<Class::MOP::Class> instance for this class.
5582521c 394
20315887 395It should also be noted that L<Class::MOP> will actually bootstrap
396this module by installing a number of attribute meta-objects into its
397metaclass.
5582521c 398
24869f62 399=back
400
1a09d9cc 401=head1 AUTHORS
24869f62 402
9fa4d0b4 403Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
404
24869f62 405Stevan Little E<lt>stevan@iinteractive.comE<gt>
406
407=head1 COPYRIGHT AND LICENSE
408
070bb6c9 409Copyright 2006-2009 by Infinity Interactive, Inc.
24869f62 410
411L<http://www.iinteractive.com>
412
413This library is free software; you can redistribute it and/or modify
8d2d4c67 414it under the same terms as Perl itself.
24869f62 415
84ef30d1 416=cut
5582521c 417